Using selects within MySQL Stored Procedures - mysql

I have stored procedure in my database and i need to look up a table and cross reference an id, then using the returned row i need to insert information into another table, but i cant seem to use the infomation from the lookup into the insert. This is what i have..
BEGIN
#Routine body goes here...
SET #UID = uid;
SET #UIDTOFB = uid_to;
SET #SQLTEST = CONCAT('SELECT users.user_auto_id FROM users WHERE users.user_fb_uid= #UIDTOFB LIMIT 1');
PREPARE sqlcmd from #SQLTEST;
EXECUTE sqlcmd;
INSERT INTO challenges(challenge_from_uid, challenge_to_uid, challenge_dateadded) VALUES(#UID, #SQLTEST.users.user_auto_id, now());
SET #LASTID = LAST_INSERT_ID();
SELECT #LASTID as id;
END
any help would be much appreciated!

This won't insert the value of #UIDTOFB since you missed some '. It takes this whole statement as one string and therefore the statement fails.
SET #SQLTEST = CONCAT('SELECT users.user_auto_id FROM users WHERE users.user_fb_uid= #UIDTOFB LIMIT 1');
PREPARE sqlcmd from #SQLTEST;
EXECUTE sqlcmd;
Anyway I'd recommend you use parameters like this:
PREPARE sqlcmd from 'SELECT users.user_auto_id FROM users WHERE users.user_fb_uid= ? LIMIT 1';
EXECUTE sqlcmd USING #UIDTOFB;
You can read more about it here in the manual.
UPDATE: Now I get, what you want to do. Do it simply like this:
SELECT #anyVariable:=users.user_auto_id FROM users WHERE users.user_fb_uid= #UIDTOFB LIMIT 1;
INSERT INTO challenges(challenge_from_uid, challenge_to_uid, challenge_dateadded) VALUES(#UID, #anyVariable, now());

Related

Can't execute a MySQL SELECT statement when inside CONCAT

I have been trying to create a simple loop of SELECT statements in MySQL to reduce code. I have started this using CONCAT() however this causes the procedure to stop/fail. For example (where k is a loop counter):
CONCAT('SELECT (Child_', k, ' INTO #Age_Child_', k, ' FROM lookup_childage WHERE ModYear = ModYear_var LIMIT 1)');
To diagnose the issue, I simply tried to place the SELECT statement (without concatenated loop variables) inside a string to then be executed. While I could get this to work for simple statements it would not work for the following:
SET #queryString = CONCAT('SELECT Child_1 INTO #Age_Child_1 FROM lookup_childage WHERE ModYear = ModYear_var LIMIT 1');
PREPARE stmt FROM #queryString;
EXECUTE stmt;
Does anyone know why the #queryString containing the CONCAT() statement will not be executed/cause the procedure to fail?
tl;dr The statement you're trying to write has the form SELECT(rest of statement) LIMIT 1. It should have the form SELECT rest of statement LIMIT 1.
It looks like you want to create variable column names, ummm, because your lookup_childage table is denormalized. I guess that table has these columns.
Child_1 INT
Child_2 INT
Child_3 INT
Child_4 INT
It looks like you hope to get a #queryString value containing this sort of thing:
SELECT Child_4 INTO #Age_Child_4 FROM lookup_childage WHERE ModYear = ModYear_var LIMIT 1
Only the 4s are variable.
So to get that string you want
SELECT CONCAT('SELECT Child_', k,
' INTO #Age_Child_', k,
' FROM lookup_childage WHERE ModYear = ModYear_var LIMIT 1'
)
INTO #queryString;

iterating over arrays in MYSQL

Is there a way to pass an array into a MySQL query and return the results as another array ?(apart from using cursors which would be an overkill for my use case)
For a single id, my query looks like this.
SET #userId = '04b452cd59dcc656'
Select user_account_number from userstore where u_id = #userId ;
Instead of sending each id at a time, I am trying to send a list and return a list
SET #userId = ('04b452cd59dcc656','eqwe52cddasfsd656');
<query returning the list of account numbers>
Also - I think this would be efficient over just sending one id at a time. Thoughts ?
You can use IN:
select user_account_number
from userstore
where u_id in ('04b452cd59dcc656', 'eqwe52cddasfsd656') ;
Using variables is trickier. If you know a maximum number, you can do:
select user_account_number
from userstore
where u_id in (#id1, #id2);
Not satisfying, but it does the job. Similarly unsatisfying is FIND_IN_SET():
set #ids = '04b452cd59dcc656,eqwe52cddasfsd656';
select user_account_number
from userstore
where find_in_set(u_id, #ids) > 0;
Alas, this won't use an index.
Finally there is dynamic SQL:
set #sql = concat('select user_account_number from userstore where u_id in (''',
replace(ids, ',', ''','''),
''')'
);
prepare s from #sql;
execute s;

How to loop through all the tables on a database to update columns

I'm trying to update a column (in this case, a date) that is present on most of the tables on my database. Sadly, my database has more than 100 tables already created and full of information. Is there any way to loop through them and just use:
UPDATE SET date = '2016-04-20' WHERE name = 'Example'
on the loop?
One painless option would be to create a query which generates the UPDATE statements you want to run on all the tables:
SELECT CONCAT('UPDATE ', a.table_name, ' SET date = "2016-04-20" WHERE name = "Example";')
FROM information_schema.tables a
WHERE a.table_schema = 'YourDBNameHere'
You can copy the output from this query, paste it in the query editor, and run it.
Update:
As #PaulSpiegel pointed out, the above solution might be inconvenient if one be using an editor such as HeidiSQL, because it would require manually copying each record in the result set. Employing a trick using GROUP_CONCAT() would give a single string containing every desired UPDATE query in it:
SELECT GROUP_CONCAT(t.query SEPARATOR '; ')
FROM
(
SELECT CONCAT('UPDATE ', a.table_name,
' SET date = "2016-04-20" WHERE name = "Example";') AS query,
'1' AS id
FROM information_schema.tables a
WHERE a.table_schema = 'YourDBNameHere'
) t
GROUP BY t.id
You can use SHOW TABLES command to list all tables in database. Next you can check if column presented in table with SHOW COLUMNS command. It can be used this way:
SHOW COLUMNS FROM `table_name` LIKE `column_name`
If this query returns result, then column exists and you can perform UPDATE query on it.
Update
You can check this procedure on sqlfiddle.
CREATE PROCEDURE UpdateTables (IN WhereColumn VARCHAR(10),
IN WhereValue VARCHAR(10),
IN UpdateColumn VARCHAR(10),
IN UpdateValue VARCHAR(10))
BEGIN
DECLARE Finished BOOL DEFAULT FALSE;
DECLARE TableName VARCHAR(10);
DECLARE TablesCursor CURSOR FOR
SELECT c1.TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS c1
JOIN INFORMATION_SCHEMA.COLUMNS c2 ON (c1.TABLE_SCHEMA = c2.TABLE_SCHEMA AND c1.TABLE_NAME = c2.TABLE_NAME)
WHERE c1.TABLE_SCHEMA = DATABASE()
AND c1.COLUMN_NAME = WhereColumn
AND c2.COLUMN_NAME = UpdateColumn;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET Finished = TRUE;
OPEN TablesCursor;
MainLoop: LOOP
FETCH TablesCursor INTO TableName;
IF Finished THEN
LEAVE MainLoop;
END IF;
SET #queryText = CONCAT('UPDATE ', TableName, ' SET ', UpdateColumn, '=', QUOTE(UpdateValue), ' WHERE ', WhereColumn, '=', QUOTE(WhereValue));
PREPARE updateQuery FROM #queryText;
EXECUTE updateQuery;
DEALLOCATE PREPARE updateQuery;
END LOOP;
CLOSE TablesCursor;
END
This is just an example how to iterate through all tables in database and perform some action with them. Procedure can be changed according to your needs.
Assuming you are using MySQL, You can use Stored Procedure.
This post is a very helpful.
Mysql-loop-through-tables

Using mySQL variables

Is it possible in a sequence of SQL statements to get the value of a field and use that to name a table in another statement? I'm not sure if that's clear, so here's an psudo-example of what I'm trying to do:
// dataType is equal to "ratings"
#var = select dataType from theTable where anID = 5;
// needs to run as "from ratings-table"
select field1,field2 from #var-table where anID = 5;
I've been reading http://dev.mysql.com/doc/refman/5.0/en/user-variables.html but either I don't properly understand this, or its not the solution I'm looking for.
Yes, you can do this using prepared statements:
SET #TableName := 'ratings';
SET #CreateQuery := CONCAT('SELECT `field1`, `field2` FROM `', #TableName, '-table` WHERE `anID` = 5');
PREPARE statementCreate FROM #CreateQuery;
EXECUTE statementCreate;

Using variables as OFFSET in SELECT statments inside mysql's stored functions

I'm quite new to subject of writting stored function for mySQL database, hence i'm not sure if what i'm trying to do here is possible at all.
I need a function that will return a column from random row from a table. I don't want to use ORDER BY RAND() method to do that, rather i would do this like this:
DECLARE MAX_COUNT INT DEFAULT 120000;
DECLARE rand_offset INT;
DECLARE str_rnd_word VARCHAR(255);
SET rand_offset = FLOOR((RAND() * MAX_COUNT));
SELECT word INTO str_rnd_word FROM all_words LIMIT 1 OFFSET rand_offset ;
RETURN str_rnd_word;
MySQL throws an error upon creating function with body like that. But when I use hard-coded number as OFFSET it works just fine.
Can someone shed some light on the subject please.
I'm running MySQL 5.0.45 on windows box.
Thanks
In MySQL before 5.5, you can't put a variable into the LIMIT clause in MySQL stored procedures. You have to interpolate it into a string and then execute the string as a dynamic query.
SET rand_offset = FLOOR(RAND() * (SELECT COUNT(*) FROM all_words));
SET #sql = CONCAT('SELECT word INTO str_rnd_word FROM all_words LIMIT 1 OFFSET ', rand_offset);
PREPARE stmt1 FROM #sql;
EXECUTE stmt1;