Want to Split string in mysql using SUBSTRING_INDEX - php

I need to assign AAA-BBB-CCC in 3 different MySQL variables.
Here's the unsuccessful code:
DELIMITER $$
USE `testdepot`$$
DROP PROCEDURE IF EXISTS `sp_test_dlr`$$
CREATE PROCEDURE `sp_test_dlr`(IN id VARCHAR(250),OUT temp1 VARCHAR(50)
,OUT temp2 VARCHAR(50),OUT temp3 VARCHAR(50))
BEGIN
DECLARE t1 VARCHAR(100);
DECLARE t2 VARCHAR(100);
DECLARE t3 VARCHAR(255);
SET #t1 = SUBSTRING_INDEX(id, '-', 1);
SET #t2 = SUBSTRING_INDEX(id, '-', -1);
SET #t3 = SUBSTRING_INDEX(id, '-', -1);
SELECT #t1 INTO temp1;
SELECT #t2 INTO temp2;
SELECT #t3 INTO temp3;
END$$
DELIMITER ;
How can I separate above AAA-BBB-CCC string?

SET #t3 = SUBSTRING_INDEX(SUBSTRING_INDEX(id, '-', -2), '-', 1);
There are other ways to do it, but I find this one quite amusing :)

Related

MySQL select if anything from the comma delmited value = anything in the comma delimited string [duplicate]

This question already has answers here:
MySQL find_in_set with multiple search string
(7 answers)
Closed 7 months ago.
I want to search multiple values from database field. below is my query.
SELECT * FROM `tablename`
WHERE FIND_IN_SET('12,13,15,15',category_id)
How i search its not working for me.
FIND_IN_SET() can only be used to search for a single value in a comma-separated list, it doesn't work with two lists.
You'll need to call it separately for each value.
SELECT * FROM tablename
WHERE FIND_IN_SET('12', category_id) OR FIND_IN_SET('13', category_id) OR FIND_IN_SET('15', category_id)
It would be better if you normalized your schema instead of using comma-separated lists. If you create a many-to-many table with the category IDs, you could do:
SELECT t1.*
FROM tablename AS t1
JOIN item_categories AS c ON t1.id = c.table_id
WHERE c.category_id IN (12, 13, 15)
FIND_IN_SET is not the solution.
Try to use REGEXP:
SELECT * FROM `tablename`
WHERE CONCAT(',', `category_id`, ',') REGEXP ',(12|13|15),';
But even if it's less pretty, it's better to use LIKE for performance reasons :
SELECT * FROM `tablename`
WHERE CONCAT(',', `category_id`, ',') LIKE '%,12,%' OR CONCAT(',', `category_id`, ',') LIKE '%,13,%' OR CONCAT(',', `category_id`, ',') LIKE '%,15,%';
I had a similar need. To solve this I created a couple of stored functions:
The first one is all_in_set(a,b), and checks if all items in a are in b:
delimiter $$
drop function if exists all_in_set;
CREATE FUNCTION all_in_set(set1 varchar(1024),set2 varchar(1024)) RETURNS boolean
NO SQL
DETERMINISTIC
COMMENT 'verify if all of the items in set1 are in set2'
BEGIN
declare i int default 0;
declare c varchar(128);
declare campos1 int;
set campos1=length(set1) - length(replace(set1, ',', '')) + 1;
set i=1;
while i<=campos1 do
set c=SUBSTRING_INDEX(SUBSTRING_INDEX(set1, ',', i), ',', -1);
if find_in_set(c,set2)=0 then
return false;
end if;
set i=i+1;
end while;
return true;
END$$
delimiter ;
for testing you can use:
> select all_in_set('a,b,c','a,b,c,d,e,f'),all_in_set('a,x,c','a,b,c,d,e,f');
+-----------------------------------+-----------------------------------+
| all_in_set('a,b,c','a,b,c,d,e,f') | all_in_set('a,x,c','a,b,c,d,e,f') |
+-----------------------------------+-----------------------------------+
| 1 | 0 |
+-----------------------------------+-----------------------------------+
The second ne is any_in_set(a,b) which returns true if at least one of the items in a is included in b.
delimiter $$
drop function if exists any_in_set;
CREATE FUNCTION any_in_set(set1 varchar(1024),set2 varchar(1024)) RETURNS boolean
NO SQL
DETERMINISTIC
COMMENT 'verify if at least one of the items in set1 is in set 2'
BEGIN
declare i int default 0;
declare c varchar(128);
declare campos1 int;
set campos1=length(set1) - length(replace(set1, ',', '')) + 1;
set i=1;
while i<=campos1 do
set c=SUBSTRING_INDEX(SUBSTRING_INDEX(set1, ',', i), ',', -1);
if find_in_set(c,set2)<>0 then
return true;
end if;
set i=i+1;
end while;
return false;
END$$
delimiter ;
for testing you can use:
> select any_in_set('x,y,c','a,b,c,d,e,f'),any_in_set('x,y,z','a,b,c,d,e,f');
+-----------------------------------+-----------------------------------+
| any_in_set('x,y,c','a,b,c,d,e,f') | any_in_set('x,y,z','a,b,c,d,e,f') |
+-----------------------------------+-----------------------------------+
| 1 | 0 |
+-----------------------------------+-----------------------------------+
1 row in set (0.018 sec)

Check if any element in an array is in a set of a mysql table [duplicate]

This question already has answers here:
MySQL find_in_set with multiple search string
(7 answers)
Closed 7 months ago.
I want to search multiple values from database field. below is my query.
SELECT * FROM `tablename`
WHERE FIND_IN_SET('12,13,15,15',category_id)
How i search its not working for me.
FIND_IN_SET() can only be used to search for a single value in a comma-separated list, it doesn't work with two lists.
You'll need to call it separately for each value.
SELECT * FROM tablename
WHERE FIND_IN_SET('12', category_id) OR FIND_IN_SET('13', category_id) OR FIND_IN_SET('15', category_id)
It would be better if you normalized your schema instead of using comma-separated lists. If you create a many-to-many table with the category IDs, you could do:
SELECT t1.*
FROM tablename AS t1
JOIN item_categories AS c ON t1.id = c.table_id
WHERE c.category_id IN (12, 13, 15)
FIND_IN_SET is not the solution.
Try to use REGEXP:
SELECT * FROM `tablename`
WHERE CONCAT(',', `category_id`, ',') REGEXP ',(12|13|15),';
But even if it's less pretty, it's better to use LIKE for performance reasons :
SELECT * FROM `tablename`
WHERE CONCAT(',', `category_id`, ',') LIKE '%,12,%' OR CONCAT(',', `category_id`, ',') LIKE '%,13,%' OR CONCAT(',', `category_id`, ',') LIKE '%,15,%';
I had a similar need. To solve this I created a couple of stored functions:
The first one is all_in_set(a,b), and checks if all items in a are in b:
delimiter $$
drop function if exists all_in_set;
CREATE FUNCTION all_in_set(set1 varchar(1024),set2 varchar(1024)) RETURNS boolean
NO SQL
DETERMINISTIC
COMMENT 'verify if all of the items in set1 are in set2'
BEGIN
declare i int default 0;
declare c varchar(128);
declare campos1 int;
set campos1=length(set1) - length(replace(set1, ',', '')) + 1;
set i=1;
while i<=campos1 do
set c=SUBSTRING_INDEX(SUBSTRING_INDEX(set1, ',', i), ',', -1);
if find_in_set(c,set2)=0 then
return false;
end if;
set i=i+1;
end while;
return true;
END$$
delimiter ;
for testing you can use:
> select all_in_set('a,b,c','a,b,c,d,e,f'),all_in_set('a,x,c','a,b,c,d,e,f');
+-----------------------------------+-----------------------------------+
| all_in_set('a,b,c','a,b,c,d,e,f') | all_in_set('a,x,c','a,b,c,d,e,f') |
+-----------------------------------+-----------------------------------+
| 1 | 0 |
+-----------------------------------+-----------------------------------+
The second ne is any_in_set(a,b) which returns true if at least one of the items in a is included in b.
delimiter $$
drop function if exists any_in_set;
CREATE FUNCTION any_in_set(set1 varchar(1024),set2 varchar(1024)) RETURNS boolean
NO SQL
DETERMINISTIC
COMMENT 'verify if at least one of the items in set1 is in set 2'
BEGIN
declare i int default 0;
declare c varchar(128);
declare campos1 int;
set campos1=length(set1) - length(replace(set1, ',', '')) + 1;
set i=1;
while i<=campos1 do
set c=SUBSTRING_INDEX(SUBSTRING_INDEX(set1, ',', i), ',', -1);
if find_in_set(c,set2)<>0 then
return true;
end if;
set i=i+1;
end while;
return false;
END$$
delimiter ;
for testing you can use:
> select any_in_set('x,y,c','a,b,c,d,e,f'),any_in_set('x,y,z','a,b,c,d,e,f');
+-----------------------------------+-----------------------------------+
| any_in_set('x,y,c','a,b,c,d,e,f') | any_in_set('x,y,z','a,b,c,d,e,f') |
+-----------------------------------+-----------------------------------+
| 1 | 0 |
+-----------------------------------+-----------------------------------+
1 row in set (0.018 sec)

MySql stored procedure validation

I need a stored procedure to perform an action according to a condition that is saved in a PHP variable. This stored procedure would run one of possible 2 insert operations:
if $var = 1 then insert 1 else insert 2
Is this possible or will I have to do 2 stored procedures and do the validation in the php script?
Example:
DELIMITER $$
CREATE PROCEDURE example_sp
(in val1 char(100), in val2 char(50), in val3 char(10), in val4 char(50))
BEGIN
IF($var = 1)
THEN
INSERT INTO table1 (val1, val2) VALUES (val1, val2);
ELSE
INSERT INTO table2 (val1, val2) VALUES (val1, val2);
END IF;
END $$
DELIMITER ;
No you need only one stored procedure.
but for this you need dynamic sql
DELIMITER $$
CREATE PROCEDURE example_sp
(IN var int, in val1 char(100), in val2 char(50), in val3 char(10), in val4 char(50))
BEGIN
IF(var = 1)
THEN
SET #sql := CONCAT("INSERT INTO table1 (",val1,",", val2,") VALUES (?,?);");
SET #a := val1;
SET #b := val2;
ELSE
SET #sql := CONCAT("INSERT INTO table2 (",val1,",", val2,") VALUES (?,?);");
SET #a := val1;
SET #b := val2;
END IF;
PREPARE stmt FROM #sql;
EXECUTE stmt USING #a,#b;
DEALLOCATE PREPARE stmt;
END $$
DELIMITER ;
And in PHP
$stmt=$db->prepare("CALL example_sp(?,?,?,?,?)");
$stmt->bind_param('issss',$var,$val1,$val2,$val3,$val4);
$stmt->execute();

Mysql function creation and selection of middle value among columns

I need to create a function in Mysql that should do the following things:
select 3 columns value from a table in the following way:
SELECT column1, column2, column3 FROM table WHERE id = value;
sort values of these columns, in order to know the greatest, the middle and the least.
return the value: (greatest+middle-least)/3
My question is doublefold:
1) is there a way to obtain the middle value, as there are GREATEST() and LEAST()?
2) why the following function return always the following error: 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 '2); END $$ DELIMITER' at line 27
DELIMITER $$
CREATE FUNCTION abc_value(partita INT)
RETURNS DOUBLE DETERMINISTIC
BEGIN
DECLARE a, b, c, column1, column2, column3 DOUBLE;
DECLARE a CURSOR FOR SELECT GREATEST(column1, column2, column3) FROM table where id = value;
DECLARE c CURSOR FOR SELECT LEAST(column1, column2, column3) FROM table where id = value;
DECLARE column1 CURSOR FOR SELECT column1 FROM table where id = value;
DECLARE quotax CURSOR FOR SELECT column2 FROM table where id = value;
DECLARE quota2 CURSOR FOR SELECT column3 FROM table where id = value;
IF column1<> a THEN
IF column1<> b THEN
SET c = column1;
END IF;
END IF;
IF column2<> a THEN
IF column2<> b THEN
SET c = column2;
END IF;
END IF;
IF column3<> a THEN
IF column3<> b THEN
SET c = column3;
END IF;
END IF;
RETURN ROUND((a+b-c)/3),2);
END$$
DELIMITER;
1) If you have 3 items and want to chose the middle one do something like this:
SELECT
value
FROM
table
ORDER BY
value
LIMIT 1,1 --index, amount (index starts from 0, so 1 is the second record)

Is there a way to make a timestamp for the last updated field on a record in MySQL?

Is there a way to add a flag in a mysql table where I can put a timestamp of the last updated field with the name of the filed in every record?
You can achieve your goal with a trigger. You don't have to take care of updating the column which indicates what was updated anymore.
See this example:
drop table if exists foo;
create table foo(a int, b int, c int,
modified timestamp on update current_timestamp,
whichOne varchar(255)
);
insert into foo (a, b, c) values (1, 2, 3), (4, 5, 6);
drop trigger if exists foomod;
delimiter $$
create trigger foomod before update on foo
for each row
begin
set #cols = '';
if old.a != new.a then
set #cols = CONCAT(#cols, ', ', 'a');
elseif old.b != new.b then
set #cols = CONCAT(#cols, ', ', 'b');
elseif old.c != new.c then
set #cols = CONCAT(#cols, ', ', 'c');
end if;
set new.whichOne = #cols;
end $$
delimiter ;
select * from foo;
Result:
a b c modified whichOne
1 2 3
4 5 6
update foo set b = 10 where b = 2;
select * from foo;
Result:
a b c modified whichOne
1 10 3 2013-06-27 12:45:29Z , b
4 5 6
Of course there's room for improvement, but you get the point, right?
ALTER TABLE `YOUR_TABLE_NAME_HERE` ADD LastUpdatedColumns TEXT NULL;
ALTER TABLE `YOUR_TABLE_NAME_HERE` ADD LastUpdated TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
Then when doing your update queries its something like this
$fieldsupdated = "field1, field2, field3";
$sql = "UPDATE `YOUR_TABLE_NAME_HERE` SET LastUpdatedColumns='$fieldsupdated';
Then if you want to report in future on the last time/date a certain column was edited you could do something like
$sql = "SELECT LastUpdated FROM `YOUR_TABLE_NAME_HERE` WHERE LastUpdatedColumns LIKE '%field1%'
There's better ways of doing it than a broad LIKE I think but I can't for the life of me think of it off the top of my head today.

Categories