IF Exists then update in mysql - mysql

New to MySQL, need help in translating the next query to MySQL
If exists (select * from INFORMATION_SCHEMA.COLUMNS where table_name= 'MyTable' and column_name = 'MyColumn')
begin
update MyTable set MyColumn='' where Code=21
end;

Based on the comments posted on your question, here is a code snippet that should answer your need. It works by first checking if the column exists in INFORMATION_SCHEMA, and then dynamically building a SQL query that is prepared, then executed. It the column does not exists, a dummy query is executed instead of the UPDATE. I tested it in this db fiddlde.
SET #dbname = DATABASE();
SET #tablename = "my_table";
SET #columnname = "my_column";
-- check if the column exists
SELECT COUNT(*) INTO #cnt
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
(table_name = #tablename)
AND (table_schema = #dbname)
AND (column_name = #columnname)
;
-- build a dynamic SQL statement
SET #preparedStatement = (SELECT IF(
#cnt > 0,
CONCAT("UPDATE ", #tablename, " SET ", #columnname, " = '' WHERE my_code = 21;"),
"SELECT 1"
));
-- run the statement
PREPARE updateIfExists FROM #preparedStatement;
EXECUTE updateIfExists;
DEALLOCATE PREPARE updateIfExists;

Related

Cannot use prepare statement on locally declared variable

In a procedure I want to select a value from a specific table in all databases. I developed a code and reached to this point:
BEGIN
DECLARE dynamic_query LONGTEXT;
SET SESSION group_concat_max_len = 100000000;
SET dynamic_query = (
SELECT
GROUP_CONCAT(
"SELECT option_name AS _key, option_value as _value from ",
TABLE_NAME,
" where option_name like '",
"something%'" SEPARATOR ' union ')
FROM
(
SELECT
CONCAT(`database_name`,'.',`table_prefix`,'options') as TABLE_NAME
FROM `tablename`
WHERE `database_name` <> '' AND `table_prefix` <> ''
) AS tmp
);
SELECT dynamic_query;
END
And I copy the output and execute it and it works fine. But when I add a prepare statement like below I get an error which is mentioned in this bug.
PREPARE result_query FROM dynamic_query;
EXECUTE result_query;
DEALLOCATE PREPARE result_query;
Is there any other way so I can get my desired output?
P.S.: I'm using SET SESSION group_concat_max_len = 100000000; to expand group_concat's limit but I prefer another way because the number of databases are growing.

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

Mysql while with variable dynamic

I need to dynamically retrieve the variable in my while, but do not know if I'm using the correct way, in the code below I need to retrieve the table name to make the inclusion, but returns an error. This test is only an example, actually I will use this procedure to create a Trigger for the tables.
Ex:
DECLARE i INT DEFAULT 0;
DECLARE tb_name VARCHAR(8000);
SET #db_name = "test_ph";
SET #qtd_tables = (SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = #db_name);
WHILE i < #qtd_tables DO
SET tb_name = (SELECT table_name FROM information_schema.tables WHERE table_schema = #db_name LIMIT i,1);
INSERT INTO tb_name(name, email) VALUES('test', 'test#test.com');
SET i = i + 1;
END WHILE;

SQL delete all from all if column A exists and equals B

How can I delete all records from all tables in a database, where the table has a column called systemid where systemid does not equal 1 or 2?
So I need to see if the table contains a certain column name, and if yes, check value of that column for all records, if not 1 or 2, delete. On all tables in the db.
Trying to clean-up a development db.
--- UPDATE ---
I found this SO thread: SQL Server : check if table column exists and remove rows
Which details the following:
IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1')
IF EXISTS( SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'TAB1' AND COLUMN_NAME = 'COL1')
delete TAB1 where COL1 not in (select COL2 from TAB2);
but I can't for the life of me correctly from a SQL query that can do what I wan to achieve due to both lack of knowledge and experience. Could anyone please provide a sample code with an explanation?
Thank you overflowers!
DECLARE #TableName VARCHAR(128);
DECLARE #MyColumn VARCHAR(128);
SET #MyColumn = 'MyColumnName'
DECLARE MyCursor CURSOR FOR
(SELECT OBJECT_NAME(c.id) as ObjectName
FROM dbo.syscolumns c
WHERE
OBJECTPROPERTY(c.id,'ISTABLE') = 1 --Search for tables only
AND c.name = #MyColumn)
OPEN MyCursor
FETCH NEXT FROM MyCursor into #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC
(
'DELETE ' + #MyColumn
+' FROM ' + #TableName
+' WHERE ' + #MyColumn + ' not in (1,2)'
)
FETCH NEXT FROM MyCursor into #TableName
END
CLOSE MyCursor
DEALLOCATE MyCursor

Something equivalent to "SELECT * FROM (SELECT table_name FROM...)"?

This query runs, but it produces the name of a table as a result, rather than actually selecting from that table.
SELECT T.*
FROM (SELECT tablename
FROM ListOfTables
WHERE id = 0) AS T
where ListOfTables contains id=0, tablename='some_table', I want to return the same result set as if I had written this directly:
SELECT * FROM some_table
Is there a native way to do this in MySQL 5, or do I have to do in in the application?
To do this in MySQL, you need to create a prepared statement which you can only create from a user variable:
SELECT #tn := tablename FROM ListOfTables WHERE id = 0;
SET #qs = CONCAT('SELECT * FROM ', #tn);
PREPARE ps FROM #qs;
EXECUTE ps;
You need to use dynamic SQL to get this result (the below code assumes SQL Server, I can't speak for other RDBMS').
declare #tableName varchar(100)
declare #query varchar(500)
select #tableName = tablename
from ListOfTables
where id = 0
select #query = 'select * from ' + #tableName
exec (#query)
Almost the same as #Shark's answer, except you also quote the name of the table to avoid syntax errors.
-- Using variables just for better readability.
DECLARE #Name NVARCHAR(4000)
DECLARE #Query NVARCHAR(4000)
-- Get the relevant data
SET #Name = QUOTENAME(SELECT tablename FROM ListOfTables WHERE id=0)
-- Build query
SET #Query = 'SELECT * FROM ' + #Schema + '.' + #Name + ''
-- execute it.
EXEC(#Query)