I need to SET a variable before my MySQL query.
Here is my query.
But it throws an error:
A new statement was found, but no delimiter between it and the previous one near (SELECT)`
I need to use this variable in my query as well. How can I solve it?
If this is outside a stored procedure, SET won't work, why not try SELECT... INTO instead?
CREATE TABLE booking_packages (adultPrice SMALLINT UNSIGNED);
INSERT INTO booking_packages VALUES (10);
SELECT adultprice INTO #adultprice FROM booking_packages;
SELECT #adultprice;
Also note that unless booking_packages only has one row, you'll need a WHERE to ensure the query only returns one row to insert into the #adultprice session variable.
Regards,
James
Related
SQL Query Forum 20210309
I’m building a Firebase Functions application that talks to a Google Cloud SQL database running MySQL 5.7. I’m trying to retrieve a value from a row in one table and, if it exists (the row or the value), insert a record in a different table.
Based on some examples I found online, my code looks like this:
DECLARE meeting_link varchar(2048) DEFAULT ""; SELECT meeting_link from campaigns where id=2 INTO meeting_link; IF LENGTH(meeting_link) > 0 THEN INSERT INTO clicks (target_id, ip_address, user_agent) VALUES (38, "ip-address", "user-agent") END IF;
In all of the different versions of this I tried, I get an 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 'DECLARE meeting_link varchar(2048) DEFAULT ""; SELECT meeting_link from campaigns' at line 1
Looking around some more, I found posts that say I can’t use DECLARE in anything but stored procedures, but I can use local variables (#ml for example) but I can’t seem to get that working correctly either.
Can someone please help me with the SQL I need for this? I need to create the record only if the record in the query exists and return the meeting_link value to my calling program.
Refer to this documentation page:
https://dev.mysql.com/doc/refman/8.0/en/sql-compound-statements.html
This section describes the syntax for the BEGIN ... END compound statement and other statements that can be used in the body of stored programs
That includes DECLARE and also IF/THEN/ELSE/END constructions. You can't use those outside of stored routines.
Here's a trick you can use instead of a stored routine:
SELECT meeting_link from campaigns where id=2 INTO #meeting_link;
INSERT INTO clicks (target_id, ip_address, user_agent)
SELECT 38, 'ip-address', 'user-agent' FROM dual WHERE LENGTH(#meeting_link) > 0;
You can use #meeting_link which is a user-defined variable, not a declared local variable.
Then instead of using IF, use FROM dual WHERE ... for your condition. The dual table is normally a pseudo-table that doesn't really exist but querying it returns 1 row. But you can make that zero rows if the condition in the WHERE clause isn't satisfied.
So the INSERT will conditionally create either one or zero rows.
Re your comment:
If you need this to be done in a single SQL statement, then one option would be to make that single SQL statement CALL a procedure that you create in your MySQL database. Then at least you could use DECLARE and IF like you were intending.
Another alternative is to combine the two statements I show above like this:
INSERT INTO clicks (target_id, ip_address, user_agent)
SELECT 38, 'ip-address', 'user-agent'
FROM campaigns WHERE id=2 AND LENGTH(meeting_link) > 0;
This works because even though you query the campaigns table, it's not mandatory to select the columns of that table. You can select constant values instead. The conditions in the WHERE clause will make this return either one row or zero rows.
I am trying to create a stored procedure in MySQL that will add rows to two different tables. The first table (sites) has an id column set to auto_increment which I would like to include in the second insert statement to the sitesByUser table. I've tried some ideas based off this excellent post: https://dba.stackexchange.com/questions/2973/how-to-insert-values-into-a-table-from-a-select-query-in-postgresql but I get various errors, such as the one listed below. I suspect that part of my problem is that I'm trying to both add both userInput and SELECT id FROM sites WHERE id=LAST_INSERT_ID() to the same table, but I'm not sure what to do to get that to work.
CREATE PROCEDURE createSite(IN siteName VARCHAR(2048), IN userInput VARCHAR(255))
BEGIN
INSERT INTO sites(siteName, user) VALUES (siteName, userInput);
INSERT INTO sitesByUser(user, site) userInput, SELECT id FROM sites WHERE id=LAST_INSERT_ID();
SELECT * FROM sitesByUser WHERE id=LAST_INSERT_ID();
END
The response from MySQL:
Error while performing Query.
ER_PARSE_ERROR
ER_PARSE_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 'userInput, SELECT id FROM sites WHERE id=LAST_INSERT_ID();
SELECT * FROM sitesBy' at line 3
Try this
SET #last_id_in_table1 = LAST_INSERT_ID();
SELECT * FROM sitesByUser WHERE id=#last_id_in_table1;
Hope this helps
It seems that the correct way to do this is to store the LAST_INSERT_ID() in a variable as described here: How to declare a variable in MySQL? I'm not sure that I should be using the # symbol in front of the variable since that seems to make it a user-defined variable which means it is session-specific which is probably too wide in scope for my needs, but so far, this successfully creates a stored procedure that I think will work. I'll update this post if it does not.
CREATE PROCEDURE createSite(IN siteName VARCHAR(2048), IN userInput VARCHAR(255))
BEGIN
INSERT INTO sites(siteName, user) VALUES (siteName, userInput);
SET #last_id_in_sites = LAST_INSERT_ID();
INSERT INTO sitesByUser(user, site) VALUES (userInput, #last_id_in_sites);
SELECT * FROM sitesByUser WHERE id=LAST_INSERT_ID();
END
so if i have a stored procedure that contains selects how to suppress the results from these selects from appearing ?
for example if i have
create procedure xyz
begin
select * from table_name #I don't want this to be seen in the console.
do other stuff
end;
You can set the required params into variables like
SET #foo = (SELECT foo_coloumn FROM foo_table);
This will suppress the select result set.
The accepted answer didn't work for me since the resultset was multirow. I did figure out a solution, though:
CREATE TEMPORARY TABLE silence_output SELECT * FROM foo;
DROP TEMPORARY TABLE silence_output;
This avoids any multirow/multicolumn issues that might be encountered by dumping the resultset into a table that is then trashed. Hope this helps someone else. You can name the temporary table anything.
I was struggling to find a way to suppress multirow output in a stored procedure while at the same time locking all applicable rows with "FOR UPDATE".
First attempt was "SELECT ... INTO" with a "LIMIT" clause but that would only lock 1 row.
Using GROUP_CONCAT solved it for me:
SELECT GROUP_CONCAT(column) INTO #variable
FROM table
WHERE column = value
FOR UPDATE
Doing that in a transaction locked all affected rows, prevented an insert, and suppressed output.
I'm having a problem with my sql query. I need to insert a data that needs to be checked first if it is existing or not. If the data is existing the sql query must return it, if not insert and return it. I already google it but the result is not quite suitable to my problem. I already read this.
Check if a row exists, otherwise insert
How to 'insert if not exists' in MySQL?
Here is a query that' I'm thinking.
INSERT INTO #tablename(#field, #conditional_field, #field, #conditional_field)
VALUES(
"value of field"
(SQL QUERY THAT CHECK IF THERE IS AN EXISTING DATA, IF NOT INSERT THE DATA and RETURN IT, IF YES return it),
"value of feild",
(SQL QUERY THAT CHECK IF THERE IS AN EXISTING DATA, IF NOT INSERT THE DATA and RETURN IT, IF YES return it)
);
Please take note that the conditional field is a required field so it can't be NULL.
Your tag set is quite weird, I'm unsure you require all the technologies listed but as long as Firebird is concerned there's UPDATE OR INSERT (link) construction.
The code could be like
UPDATE OR INSERT INTO aTable
VALUES (...)
MATCHING (ID, SomeColumn)
RETURNING ID, SomeColumn
Note that this will only work for PK match, no complex logic available. If that's not an option, you could use EXECUTE BLOCK which has all the power of stored procedures but is executed as usual query. And you'll get into concurrent update error if two clients execute updates at one time.
You could split it out into 2 steps
1. run a select statement to retrieve the rows that match your valus. select count (*) will give you the number of rows
2. If zero rows found, then run the insert to add the new values.
Alternatively, you could create a unique index form all your columns. If you try to insert a row where all the values exist, an error will be returned. You could then run a select statement to get the ID for this existing row. Otherwise, the insert will work.
You can check with if exists(select count(*) from #tablename) to see if there is data, but with insert into you need to insert data for all columns, so if there is only #field missing, you cant insert values with insert into, you will need to update the table and go with a little different method. And im not sure, why do you check every row? You know for every row what is missing? Are you comparing with some other table?
You can achieve it using MySQL stored procedure
Sample MySQL stored procedure
CREATE TABLE MyTable
(`ID` int, `ConditionField` varchar(10))
;
INSERT INTO MyTable
(`ID`, `ConditionField`)
VALUES
(1, 'Condition1'),
(1, 'Condition2')
;
CREATE PROCEDURE simpleproc (IN identifier INT,ConditionData varchar(10))
BEGIN
IF (SELECT ID FROM MyTable WHERE `ConditionField`=ConditionData) THEN
BEGIN
SELECT * FROM MyTable WHERE `ConditionField`=ConditionData;
END;
ELSE
BEGIN
INSERT INTO MyTable VALUES (identifier,ConditionData);
SELECT * FROM MyTable WHERE `ConditionField`=ConditionData;
END;
END IF;
END//
To Call stored procedure
CALL simpleproc(3,'Condition3');
DEMO
I am trying to create an sql trigger statement using phpmyadmin trigger interface.
Trying to do something for table 1 as shown below :
BEGIN
declare #valid_number int ;
select id into #valid_number from table 2 ;
if 10 does not exist in #valid_number then
{do something here}
end if;
END
how to achieve it?
First: a variable in a stored routine can't store multiple values, just a single one. Your statement
select id into #valid_number from table 2 ;
will only work, if the query returns exactly one row. An error will occur, if the query returns multiple rows, a warning, if the query returns no row at all, see the manual page to SELECT ... INTO:
The INTO clause can name a list of one or more variables, which can be
user-defined variables, stored procedure or function parameters, or
stored program local variables. [...]
The selected values are assigned to the variables. The number of
variables must match the number of columns. The query should return a
single row. If the query returns no rows, a warning with error code
1329 occurs (No data), and the variable values remain unchanged. If
the query returns multiple rows, error 1172 occurs (Result consisted
of more than one row).
Solution:
It's not difficult to create a statement that gives you the desired answer in exact one row, i.e.
SELECT COUNT(*) into valid_number FROM example WHERE id = 10;
This query will return 0, if the id 10 does not exists in column id and the count of occurences else. Of course there are several ways to achieve this, this is just one of them. You could rewrite your stored routine to:
BEGIN
-- prefer local variables, don't use user defined, if not needed.
DECLARE valid_number int;
SELECT COUNT(*) into valid_number FROM example WHERE id = 10;
IF valid_number = 0 THEN
-- do something here
END IF;
SELECT result;
END
Note
You could use a cursor to traverse the result of a query, but most times one wants to avoid a cursor. To use a cursor under similar conditions as of this question would not be the SQL way to do it and most times very inefficient.