I am using a prepared statement to insert data from table 1 into table 2 (a copy of table 1)
Only difference is table 2 has a DateTime column. I am trying to insert the data from table 1 into table 2. But how can I add the datetime(current time and date)?
I am a little suck on how to add this into my prepared statement.
DECLARE sqlquery text;
SET sqlquery = CONCAT('insert into partial_log select inaid, `PartNo`,`LineCode`,`EPartsPartNo`,`Surcharge`,`Price`,`CustomerDescription`,`ShortCode`,`PlusCode`,`LiveDate`,`CustomerPartNo`,`Alt1LineCode`,`Alt1PartNo`,`Alt1EPartsPartNo`,`Alt2LineCode`,`Alt2PartNo`,`Alt2EPartsPartNo`,`Alt3LineCode`,`Alt3PartNo`,`Alt3EPartsPartNo`,`Alt4LineCode`,`Alt4PartNo`,`Alt4EPartsPartNo`,`Alt5LineCode`,`Alt5PartNo`,`Alt5EPartsPartNo`,`Alt6LineCode`,`Alt6PartNo`,`Alt6EPartsPartNo`,`Alt7LineCode`,`Alt7PartNo`,`Alt7EPartsPartNo`,`Alt8LineCode`,`Alt8PartNo`,`Alt8EPartsPartNo`,`Alt9LineCode`,`Alt9PartNo`,`Alt9EPartsPartNo`,`Alt10LineCode`,`Alt10PartNo`,`Alt10EPartsPartNo`,',NOW(),',FROM itable order by `LineCode`,`PartNo`;');
set sqlquery=REPLACE(sqlquery,'inaid',inaid);
set sqlquery=REPLACE(sqlquery,'itable',itable);
SET #stat = sqlquery;
PREPARE stmt from #stat;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
I have tried to add Now() by using concat but this does not work and throws invalid syntax error.
#42000You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '14:00:06,FROM Ats order by LineCode,PartNo' at line 1
UPDATE:
Do not need CONCAT to add NOW() into the statement.
DECLARE sqlquery text;
SET sqlquery = 'insert into partial_log select inaid, `PartNo`,`LineCode`,`EPartsPartNo`,`Surcharge`,`Price`,`CustomerDescription`,`ShortCode`,`PlusCode`,`LiveDate`,`CustomerPartNo`,`Alt1LineCode`,`Alt1PartNo`,`Alt1EPartsPartNo`,`Alt2LineCode`,`Alt2PartNo`,`Alt2EPartsPartNo`,`Alt3LineCode`,`Alt3PartNo`,`Alt3EPartsPartNo`,`Alt4LineCode`,`Alt4PartNo`,`Alt4EPartsPartNo`,`Alt5LineCode`,`Alt5PartNo`,`Alt5EPartsPartNo`,`Alt6LineCode`,`Alt6PartNo`,`Alt6EPartsPartNo`,`Alt7LineCode`,`Alt7PartNo`,`Alt7EPartsPartNo`,`Alt8LineCode`,`Alt8PartNo`,`Alt8EPartsPartNo`,`Alt9LineCode`,`Alt9PartNo`,`Alt9EPartsPartNo`,`Alt10LineCode`,`Alt10PartNo`,`Alt10EPartsPartNo`, NOW() FROM itable order by `LineCode`,`PartNo`;';
set sqlquery=REPLACE(sqlquery,'inaid',inaid);
set sqlquery=REPLACE(sqlquery,'itable',itable);
SET #stat = sqlquery;
PREPARE stmt from #stat;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
The CONCAT is totally unnecessary, and just adding to your confusion.
Your query can be written like this
SET sqlquery = 'insert into partial_log
select inaid, `PartNo`,`LineCode`,
`EPartsPartNo`,`Surcharge`,`Price`,
`CustomerDescription`,`ShortCode`,`PlusCode`,
`LiveDate`,`CustomerPartNo`,`Alt1LineCode`,
`Alt1PartNo`,`Alt1EPartsPartNo`,`Alt2LineCode`,
`Alt2PartNo`,`Alt2EPartsPartNo`,`Alt3LineCode`,
`Alt3PartNo`,`Alt3EPartsPartNo`,`Alt4LineCode`,
`Alt4PartNo`,`Alt4EPartsPartNo`,`Alt5LineCode`,
`Alt5PartNo`,`Alt5EPartsPartNo`,`Alt6LineCode`,
`Alt6PartNo`,`Alt6EPartsPartNo`,`Alt7LineCode`,
`Alt7PartNo`,`Alt7EPartsPartNo`,`Alt8LineCode`,
`Alt8PartNo`,`Alt8EPartsPartNo`,`Alt9LineCode`,
`Alt9PartNo`,`Alt9EPartsPartNo`,`Alt10LineCode`,
`Alt10PartNo`,`Alt10EPartsPartNo`, NOW()
FROM itable order by `LineCode`,`PartNo`;');
In fact as long as the columns are all in the same order in both the partial_log and itable tabless with only the addition of the new column datetime at the end of partial_log you could write the query like this
SET sqlquery = 'insert into partial_log
SELECT a.*, NOW()
FROM itable a
ORDER BY a.LineCode,a.PartNo
Related
I am trying to executing a mysql query like this
SET #id := '47';
SET #table := #id+'_2013_2014_voucher';
SELECT * FROM #table;
Delete FROM #table where id=#id
It showing error like this
[Err] 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 '#table' at line 1
How I can achieve that?
The usage of dynamic table names within the query is best with Prepared Staments,
also in mysql for concatenation the function is concat
SET #id := '47';
SET #table := concat(#id,'_2013_2014_voucher');
set #qry1:= concat('select * from ',#table);
prepare stmt from #qry1 ;
execute stmt ;
You can do it for the delete query as well
You need to use prepared statements for dynamic table name. Prepared statements support parameters, but you can't use them for table names.
Also to put strings together you have to use CONCAT().
Oh, and you have to do all this in a stored procedure.
Create one like this:
DELIMITER $$
CREATE PROCEDURE sp_exec_dynStmt()
BEGIN
SET #id := 47; /*The single-quotes made it a string, that's not necessary*/
SET #table := CONCAT(#id, '_2013_2014_voucher');
SET #sql := CONCAT('SELECT * FROM ', #table, ';');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET #sql = CONCAT('DELETE FROM ', #table, ' WHERE id = ?;'); /*The id can be a parameter, but not the table name*/
PREPARE stmt FROM #sql;
EXECUTE stmt USING #id;
END $$
DELIMITER ;
Then execute it like this:
CALL sp_exec_dynStmt();
try changing that line with
SET #table = '`' + #id+'_2013_2014_voucher`';
usually I declare variable in this way
SET #id = '47'; (without :)
you should use only : with SET, := to assigning variable in a SELECT
I'm creating a Twitter clone using MySQL and I'm writing a stored procedure to update userfeed table of a user who just followed someone new to include all the tweets of the person whom the user has followed.
CREATE PROCEDURE `populate_userfeed_after_following`(IN username varchar(20), IN following_username varchar(20))
BEGIN
DECLARE last_tweet timestamp default null;
DECLARE following_id int;
SELECT id from users where username=following_username into following_id;
SET #timestamp_tweet = CONCAT('SELECT timestamp FROM userfeed_', username, ' ORDER BY timestamp DESC LIMIT 1 into', last_tweet);
PREPARE timestamp_tweetQuery FROM #timestamp_tweet;
EXECUTE timestamp_tweetQuery;
IF (last_tweet is NULL) THEN
SET #insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
WHERE author=', following_id,
' LIMIT 200');
ELSE
SET #insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
WHERE author=', following_id ,'and timestamp >', last_tweet);
END IF;
PREPARE insertQuery FROM #insert_statement;
EXECUTE insertQuery;
DEALLOCATE PREPARE timestamp_tweetQuery;
DEALLOCATE PREPARE insertQuery;
END
I'm storing the most out-of-date timestamp in a local variable called last_tweet after retrieving it from the userfeed table of the user who followed someone and which I'm checking to be NULL to create a dynamic insert statement.
Whenever I call the procedure by passing the parameters, e.g.,
call populate_userfeed_after_following('joe', 'rocky');
#joe follows rocky
I get an error,
Error Code: 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 'NULL' at line 1
I would appreciate if you point out the mistake in my code.
As #P.Salmon pointed out, use of local variables (using DECLARE statement) would not work in this situation. So I corrected the code to use session variables or user-defined variables (using SET statement) and rewrote it.
The following logic works:
CREATE PROCEDURE `populate_userfeed_after_following`(IN username varchar(20), IN following_username varchar(20))
BEGIN
-- DECLARE last_tweet timestamp default null;
-- DECLARE following_id int;
SET #following_id = 0;
SET #last_tweet = NULL;
SET #followingId_tweet = CONCAT('SELECT id from users where username=\'', following_username, '\' into #following_id');
SET #timestamp_tweet = CONCAT('SELECT timestamp FROM userfeed_', username, ' ORDER BY timestamp DESC LIMIT 1 into #last_tweet');
PREPARE followingIdQuery FROM #followingId_tweet;
EXECUTE followingIdQuery;
DEALLOCATE PREPARE followingIdQuery;
PREPARE timestamp_tweetQuery FROM #timestamp_tweet;
EXECUTE timestamp_tweetQuery;
DEALLOCATE PREPARE timestamp_tweetQuery;
IF (#last_tweet is NULL) THEN
SET #insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
WHERE author=#following_id
LIMIT 200');
ELSE
SET #insert_statement = CONCAT('INSERT INTO userfeed_', username, '(tweet_id) SELECT id from tweets
WHERE author=#following_id and timestamp > #last_tweet');
END IF;
PREPARE insertQuery FROM #insert_statement;
EXECUTE insertQuery;
DEALLOCATE PREPARE insertQuery;
END
The initial error was due to the select statement where I was using the value passed in the parameter to create a dynamic SQL statement and the line below that where SET #timestamp_tweet was used. The correct way to do that was to use prepared statements instead.
I am working in a stored procedure that is fetching queries from a table and execute them.
The problem is that I have some queries with single/doubled quotes and it is throwing an error on execute them.
Procedure
delimiter $$
drop procedure if exists run_change_ids_queries$$
create procedure run_change_ids_queries()
begin
declare s_query TEXT;
declare done bool default false;
declare c_queries cursor for
select `query` from `queries` WHERE `executed` = 0 ORDER BY `qry_id` ASC;
declare continue handler for not found set done = true;
open c_queries;
read_loop: loop
fetch c_queries into s_query;
if done then
leave read_loop;
end if;
-- run the query
set #sql = s_query;
prepare stmt from #sql;
execute stmt;
deallocate prepare stmt;
-- update executed flag on query
set #update = CONCAT('UPDATE `queries` SET `executed` = 1 WHERE `query` LIKE \'',#sql,'\';');
prepare stmt from #update;
execute stmt;
deallocate prepare stmt;
end loop;
end$$
Query update urisegments as s inner join change_product_ids as p on concat('{"product_id":"', p.old_id, '"}') = s.primary_key_value set s.primary_key_value = CONCAT('{"product_id":', p.new_id, '"}') where s.app_namespace = 'Shop' and s.primary_key_value like '%product_id%'; is throwing error: [42000][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 '{"product_id":"', p.old_id, '"}') = s.primary_key_value set s.primary_key_value ' at line 1
Workaround #01
I already tried to escape single/doubled quotes into \' and \" respectively, but it throws another error:
[42000][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 '\'{\"product_id\":\"\', p.old_id, \'\"}\') = s.primary_key_value set s.primary_k' at line 1.
Don't try to concatenate the query into the SQL. Prepared statements can contain placeholders, which you fill in when you use the EXECUTE statement.
set #update = 'UPDATE `queries` SET `executed` = 1 WHERE `query` = ?');
prepare stmt from #update;
execute stmt USING #sql;
The statement is not escaped.
All single/doubled quotes should be escaped.
update urisegments as s
inner join change_product_ids as p on concat(\'{\"product_id\":\"\', p.old_id, \'\"}\') = s.primary_key_value
set s.primary_key_value = CONCAT(\'{\"product_id\":\', p.new_id, \'\"}\')
where s.app_namespace = \'Shop\' and s.primary_key_value like \'%product_id%\';
Instead of testing for the query, test for its id:
... WHERE qry_id = ?
(Add that column to the initial SELECT.)
I wrote this code and when I execute it it says I have a problem with mysql syntax near the update statement
set #s1 = (select if ((select count(*) from information_schema.columns where table_name='foo' and column_name='bar_id') > 0,
'select 1',
'alter table foo add column bar_id bigint; update foo set bar_id = baz_id;'));
prepare stmt from #s1;
execute stmt;
deallocate prepare stmt;
If I change my code to
set #s1 = (select if ((select count(*) from information_schema.columns where table_name='foo' and column_name='bar_id') > 0,
'select 1',
'alter table foo add column bar_id bigint;'));
prepare stmt from #s1;
execute stmt;
deallocate prepare stmt;
update foo set bar_id = baz_id;
then it works. but I want the update statement inside the if condition.
I cannot make this into a SP.
Error:
ERROR 1064 (42000): 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 'update foo set bar_id = baz_id' at line 1
In your first code block, you attempt to prepare a string that contains two SQL statements. Unfortunately, MySQL prepare / execute cannot have multiple statements.
If you can't use SP, I think I'd suggest doing this like so:
set #s1 = (select if ((select count(*) from information_schema.columns where table_name='foo' and column_name='bar_id') > 0,
'select 1',
concat('alter table foo add column bar_id bigint default ', baz_id)));
prepare stmt from #s1;
execute stmt;
deallocate prepare stmt;
alter table foo alter column bar_id drop default;
But, honestly, I'd suggest you minimize DDL changes as those can have unpredictable run-time behavior. In this case, that means adding the foo.bar_id out-of-band and just perform an update as needed.
The problem is that MySQL's prepared statements do not support multi-statements.
If you want to script the database structure updates, easiest way is to use a procedure without dynamic SQL (you might want to check the table_schema as well when you are doing the changes).
create procedure sp_fix_structure()
begin
declare v_cnt int;
select count(*) into v_cnt
from information_schema.columns
where table_schema=database() and table_name='foo' and column_name='bar_id';
if (v_cnt=0) then
alter table foo add column bar_id bigint;
update foo set bar_id = baz_id;
end if;
end
Myself trying to pass string variable to where condition in MySQL query as given in this stack overflow answer as given below.
select #start := ' and Id=21';
select * from myTable where 1=1 #start;
So how can I use string variable with where condition in MySQL queries. The variables are set dynamically and the query runs within procedure.
EDIT: I also tried
SET #start = ' Id=21 ';
select * from myTable where (select #start);
But no use.
No you cannot do that. The columns and the condition in the select clause needs to be fixed when you are preparing the select statement.
So you cannot make a dynamic where clause statement like the one you posted. In that example, the values in the column are dynamic not the column names.
The manual says:
A conditional object consists of one or more conditional fragments
that will all be joined by a specified conjunction. By default, that
conjunction is AND.
I believe what you are attempting is to create a Dynamic Query using EXEC command.
You can create a varchar variable with the SQL statement and then execute it with EXEC, here an example taken from
https://www.mssqltips.com/sqlservertip/1160/execute-dynamic-sql-commands-in-sql-server/
If you want to do something like
DECLARE #city varchar(75)
SET #city = 'London'
SELECT * FROM customers WHERE City = #city
This is the Dynamic Query creation.
DECLARE #sqlCommand varchar(1000)
DECLARE #columnList varchar(75)
DECLARE #city varchar(75)
SET #columnList = 'CustomerID, ContactName, City'
SET #city = '''London'''
SET #sqlCommand = 'SELECT ' + #columnList + ' FROM customers WHERE City = ' + #city
EXEC (#sqlCommand) --This does the magic
/*
just a heads up, the user impersonating the execution needs credentials for EXEC command.
*/
Store part of your query
SET #start = ' and Id=21';
Store your query concatenating its parts
SET #s = CONCAT('select * from myTable where 1=1 ', #start);
Prepare a statement for execution
PREPARE stmt FROM #s;
EXECUTE executes a prepared statement
EXECUTE stmt;
Release the prepared statement
DEALLOCATE PREPARE stmt;
All together:
SET #start = ' and Id=21';
SET #s = CONCAT('select * from myTable where 1=1 ', #start);
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
More Details on the MySQL manual: https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html