MySql stored procedure validation - php

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();

Related

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)

PHP: create and run PostGres Procedure (BEGIN ... END) with binding parameters

I am using Postgres with PHP, I have two dependent queries as below:
INSERT INTO tab2
SELECT * FROM tab1 WHERE col1 = $1 AND col2 IS NOT NULL;
DELETE FROM tab1 WHERE col1 = $1 AND col2 IS NOT NULL ;
I want these both to run or none of them. So I created below code block:
DO $$
BEGIN
INSERT INTO tab2
SELECT * FROM tab1 WHERE col1 = $1 AND col2 IS NOT NULL ;
DELETE FROM tab1 WHERE col1 = $1 AND col2 IS NOT NULL ;
END$$
But this is not working and giving below error:
ERROR: bind message supplies 1 parameters, but prepared statement "" requires 0
PHP Code:
$result = pg_query_params($pg_con_write,$query_PG,array($Param1));
I think I can't use Bind Parameters in this way... So please suggest the best possible way to do so...
I think $$ is the issue, you should rewrite your query like:
BEGIN;
INSERT INTO tab2
SELECT * FROM tab1 WHERE col1 = $1 AND col2 IS NOT NULL;
DELETE FROM tab1 WHERE col1 = $1 AND col2 IS NOT NULL;
COMMIT;

MySQL procedure returning incorrect value to PHP

I have this stored procedure that inserts data into the event table. The problem is that the value returned to PHP in select lastNum; is 1 lower (inserted as 2 but will return 1) than when it is used in the previous insert statement. This doesn't make any sense to me as the value is not changed in between the 2 lines.
DROP PROCEDURE IF EXISTS `insertEvent`$$
CREATE DEFINER=`root`#`localhost` PROCEDURE `insertEvent`(ptitle varchar(500), pdescription varchar(500), pxcoord int(4), pycoord int(4), ptype char(1), pnumber int(11))
begin
declare numExists int(1);
declare lastNum int(9);
select count(*) from event where `number`=pnumber;
select insAndIncEventId() into lastNum from dual;
if numExists > 0 then
update event set `number`=`number`+1 where `number`>=pnumber;
end if;
insert into event (id, title, description, xcoord, ycoord, `type`, `number`) values (lastNum, ptitle, pdescription, pxcoord, pycoord, ptype, pnumber);
select lastNum;
end$$
drop function if exists `insAndIncEventId`$$
create function `insAndIncEventId`() returns int(9)
begin
declare event_id int(9);
select nextId into event_id from eventid;
update eventid set nextid=nextid+1;
return event_id;
end$$
The PHP is as follows:
$eventid=$eventidstmt->fetch(PDO::FETCH_BOTH);
fb("event id count from sql:".count($eventid));
fb("event id from sql:".$eventid[0]);

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)

Want to Split string in mysql using SUBSTRING_INDEX

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 :)

Categories