I have a MYSQL database that needs some data removed from a field.
My current data is like this..
gttp://www.somesite.com?ref=1234567
gttp//notquitealink.com/ref.php?r=myreferral
I am trying to remove the gttp://www.somesite.com?ref= to leave only the last part after the =
so I want the data to look like this
1234567
myreferral
I found this code from a previous question. MySQL Regex Search and replace
DELIMITER $$
CREATE FUNCTION `regex_replace`(pattern VARCHAR(1000),replacement VARCHAR(1000),original VARCHAR(1000))
RETURNS VARCHAR(1000)
DETERMINISTIC
BEGIN
DECLARE temp VARCHAR(1000);
DECLARE ch VARCHAR(1);
DECLARE i INT;
SET i = 1;
SET temp = '';
IF original REGEXP pattern THEN
loop_label: LOOP
IF i>CHAR_LENGTH(original) THEN
LEAVE loop_label;
END IF;
SET ch = SUBSTRING(original,i,1);
IF NOT ch REGEXP pattern THEN
SET temp = CONCAT(temp,ch);
ELSE
SET temp = CONCAT(temp,replacement);
END IF;
SET i=i+1;
END LOOP;
ELSE
SET temp = original;
END IF;
RETURN temp;
END$$
DELIMITER ;
I ran it and it created a function that I could query on.
When I run this query....
UPDATE `tb_te_builder_user` SET tebu_refID = regex_replace('gttp(.*)=', '',tebu_refID);
I get 0 rows affected. (Query took 10.9480 sec)
But when I try to do a select
SELECT * FROM `tb_te_builder_user` WHERE tebu_refID REGEXP 'gttp(.*)='
I get well over 7,000 records returned.
I am not quite sure what to make of it... I think I am missing something very simple here.
I was also looking at this solution https://github.com/mysqludf/lib_mysqludf_preg#readme but I don't have rights to use the make command on my server. So I am left with trying to figure out what I am doing incorrectly.
Any help is appreciated.
That function only works for a single character pattern. This limitation is mentioned at the source site.
For a string pattern you may use a user defined function, eg. mysql-udf-regexp, see How to do a regular expression replace in MySQL?. However, to install a user defined function you need to compile it and add it to the MySQL installation.
MariaDB, a MySQL drop-in replacement, has a builtin function regex_replace fully supporting string patterns.
If you cannot do any of these you may try an external solution, eg. using PHP and PHP's preg_replace function.
Related
Hi I've got a problem managing CASE WHEN or IF Statements in a CREATE FUNCTION Call in DB2
I tried this Statement:
CREATE OR REPLACE FUNCTION NAECHSTES_DATUM(PARAM1 CHAR(6), PARAM2 DATE)
RETURNS DATE
LANGUAGE SQL
BEGIN
DECLARE BASEDATE DATE;
DECLARE THATDATE DATE;
SET BASEDATE = TO_DATE(CONCAT(PARAM1,CAST(YEAR(PARAM2) AS CHAR(4))),'DD.MM.YYYY');
IF (BASEDATE >= PARAM2)
THEN SET THATDATE = BASEDATE;
ELSE SET THATDATE = BASEDATE + 1 YEAR;
END IF;
RETURN THATDATE;
END
I get this error
[-104] Auf "+ 1 YEAR" folgte das unerwartete Token "END-OF-STATEMENT". Mögliche Tokens: "
END IF".. SQLCODE=-104, SQLSTATE=42601, DRIVER=4.14.113
Similar result when I use CASE WHEN.
Do you know where the problem could be?
Use an alternative statement delimiter after the END of the function.
Inside the function the statement delimiter is the semicolon (;)
But Db2 needs to know an additional delimiter to indicate the end of the block.
For the Db2 command line (in shell scripts, batch files) you can use the "-td#" command line option and terminate the block with the # character. Inside a file that contains the function you can use:
--#SET TERMINATOR #
anywhere before the function block and then terminate the block with #
If you are use a GUI tool to submit the DDL or SQL, each GUI tool has its own way to specify alternative statement delimiters. Look at the settings and properties. It's always wise to fully describe your toolset (which programs, which versions, which operating system etc) in your question.
I have an issue which i'm hoping someone out there will be able to assist.
I'm trying to write a trigger which takes the datetime stamp and puts just the date into a new column. But likewise, also if a value in a different column is equal to x, then replace it with y.
I can get individual statements to work (i.e if I have just the date code or the replacement code individually it works fine), but I can't get them to both work in the same trigger.
SET NEW.date = LEFT(NEW.entrydate, 10);
IF
(NEW.connect_ip = "1.2.3.4")
THEN SET
NEW.connect_ip = "0.0.0.0";
END IF
Multi-statement triggers need BEGIN and END around their "body", and usually DELIMITER overridden around their declaration.
Example/Template:
DELIMITER $$
CREATE TRIGGER [blah blah]
BEGIN
[do stuff]
END$$
DELIMITER ;
Alternatively, for your specific case, I noticed an answer the other day with a possiblity I had overlooked; you can set multiple things in a SET statement:
SET NEW.date = LEFT(NEW.entrydate, 10)
, NEW.connect_ip = IF(NEW.connect_ip = "1.2.3.4", "0.0.0.0", "1.2.3.4")
;
I'am developing a small project with PHP and MySql on a Wamp server. I just discovered the wonderful principle of SQL triggers. Hum... well. It would be wonderful if I could use it.
Indeed I have a problem with the following script:
BEGIN
SET #liste = NEW.reponse
WHILE LEN(#liste) > 0
BEGIN
IF PATINDEX('%,%',#liste) > 0
BEGIN
SET #choix = SUBSTRING(#liste, 0, PATINDEX('%,%', &liste))
INSERT INTO resultat (referendum, choix) VALUES (NEW.id, #choix)
SET #liste = SUBSTRING(#liste, LEN(#choix + ',') + 1, LEN(#liste))
END
END
END
I would like to execute this trigger after the insertion of a record in table "Referendum". In this table, there is a field "reponse" which contains the different possible answers. This field contains this kind of data: "Yes,No,I don't know". For each new question, I want to insert a new record in table "Resultat" per possible answer.
In my example, three new records: one for Yes, one for No and one for I don't know.
My code comes from an example on the internet but it doesn't work properly. SQL returns a syntax error with message "While_Sym expected"...
I tried to add semicolon following what I found on the internet but no way...
I guess you need something like this:
CREATE TRIGGER mytrigger AFTER INSERT
ON Referendum FOR EACH ROW
BEGIN
DECLARE cnt int;
DECLARE str varchar(100);
Set cnt = CHAR_LENGTH(NEW.reponse)
- CHAR_LENGTH(Replace(NEW.reponse,',','')) +1;
WHILE cnt > 0 DO
Set str = SUBSTRING_INDEX(
SUBSTRING_INDEX( New.reponse,',', -cnt)
,',',1);
INSERT INTO resultat (referendum, choix)
VALUES (NEW.id, str);
Set cnt = cnt - 1;
END WHILE;
END;
Demo: http://sqlfiddle.com/#!2/c7321/1
Some thoughts:
There are no PATINDEX nor LEN functions in MySql, they come from SQL Server.
Most functions are not standard in SQL, one shouldn't expect that something that works on database X should also work on database Y (and vice versa)
You always need to check the manual.
There is difference in MySql between #variable and variable - they are not the same (opposite to SQL Server where there is only one kind of variables --> #variable).
Please refer to documentation to learn about #user_definied_variables and local_variables
http://dev.mysql.com/doc/refman/5.7/en/user-variables.html
http://dev.mysql.com/doc/refman/5.7/en/declare-local-variable.html
Depending on your client software you may need to use also DELIMITER xx command, for example in mysql console client or MySql-Workbench you need something like this to create a trigger without syntax errors:
DELIMITER $$
CREATE TRIGGER mytrigger AFTER INSERT
ON Referend ......
......
......
END;
$$
DELIMITER ;
I am converting an old dataset into a newly structured database. Currently they have data in this format:
[quantity int]~[var1 string]|[var2 string optional]|[var3 string optional];(etc);
[quantity]~[var1]|[var2]|[var3]
where various patterns are delimited first by semicolons, then by tildes, and finally by pipe characters within the same field (no brackets) within the existing database. For instance:
3~S|Red|Top;1~S|Blue|Top; ... etc ... ;20~XL|Green|Left
I want to take that string in each record and do the following:
Create a new record in an existing table based off each semicolon split
Split each token again by the tilde, putting the first piece into one field and the second into a separate field (I don't care about splitting by pipe) in the same record
I don't know if it's even possible, but I'm hoping that it is. I am also hoping to only have to do this once, as the new system will take care of creating all this crap automatically. My sproc-fu is quite awful in MySQL, so any help is much appreciated.
Thanks so much!
This seems like a pretty gross thing to do in SQL, but here's a proof-of-concept script.
If the output looks right to you, replace the SELECT with an appropriate INSERT statement and it should get you what you want.
delimiter ;;
drop procedure if exists load_crazy_stuff;;
create procedure load_crazy_stuff(in s longtext)
begin
declare pos int;
declare record longtext;
declare leftpart int;
declare rightpart longtext;
set s = concat(s,';');
while length(s)>0 DO
set pos = instr(s,';');
set record = left(s,pos-1);
set s = substr(s,pos+1);
set pos = instr(record,'~');
set leftpart = left(record,pos-1);
set rightpart = substr(record,pos+1);
select leftpart, rightpart;
end while;
end;;
call load_crazy_stuff('3~S|Red|Top;1~S|Blue|Top;20~XL|Green|Left');;
The non-gross way to do it is this:
load data infile '/tmp/your-data-file' into table yourtable fields terminated by '~' lines terminated by ';';
Over the last couple of days I have tried to write an Stored procedure in MySQL and I have some truble getting it to work. Hope someone here can give me some input :)
The example I post is for asp.Net Membership provider to create a new user. I expect to send email and password to the DB and get an int return to verify that the userdeatils was written to the DB.
I use a MySQL DB 5.1 (I think) and write the SQL to a webinterface.
I got 2 sidequestions, can someone explain that too :):
1) I use a DELIMITER, but do not know what it does.
2) I am not sure if I have to do other things then to set autocommit = 0 to get transactions to work, or if I even have to do that.
I know that I could have used a IF / ELSE statement instead of a transaction, but would like to do it with one to find out how it works. (I expect to use it alot later)
The code I can not get to work:
DELIMITER //
CREATE DEFINER=`websharp_dk`#`%` PROCEDURE `CreateUser`(
IN _username VARCHAR(100),
IN _Password VARCHAR(100))
RETURNS INT
BEGIN
SET autocommit = 0;
DECLARE return_value INT;
BEGIN TRY
START TRANSACTION
INSERT INTO User
(Email
,Password
,Failed_Password_Count
,Creation_Date)
VALUES
(_username
,_Password
,0
,Datetime.Now())
SET return_value = 1;
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK
SET return_value = 0;
END CATCH
BEGIN FINALLY
RETURN return_value;
END FINALLY
END//
DELIMITER ;
Edit:
The error message I get is:
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'INT BEGIN SET autocommit = 0; DECLARE return_value INT; ' at line 4
To get support for transactions, make sure you are using the InnoDB storage engine rather than the default MyISAM.
As far as that code itself, my first question would be, why are you wrapping that single query in a transaction? Also, what errors are you seeing?
The delimiter redefines what sequence of characters you use to end an sql statement. The entire create procedure is one big statement and you need to tell MySQL where it ends with something (would normally be ';'). But since you have a bunch of other statements in the "body" (between BEGIN and END) of the create procedure statement that all need to be ended too you need to redefine the delimiter so you don't end the create procedure statement at the first ';'.
Without redefining the delimiter, MySQL would think that the create procedure statement looked like this and then begin a new statement:
CREATE DEFINER=`websharp_dk`#`%` PROCEDURE `CreateUser`(
IN _username VARCHAR(100),
IN _Password VARCHAR(100))
RETURNS INT
BEGIN
SET autocommit = 0;
Using DELIMITER ; at the end of the script changes the delimiter back to ';' and is not needed although it's good practice to do so.