How do you use user variables in Mysql If clause? - mysql

I want to alter a table and add a column to it if it doesn't already exist. So I populate a variable #row and if it's I want to alter the able as so.
SET #row = (SELECT count(*) FROM information_schema.COLUMNS WHERE TABLE_NAME='tblname' AND COLUMN_NAME='colname' and table_schema='dbname');
IF(#row <1) THEN
ALTER TABLE tblname ADD colname INT;
END IF;
But I am getting a syntax error
#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 'IF(#row <1) THEN ALTER TABLE tblname ADD colname INT' at line 1
What am I doing wrong?

In MySQL you need a shell around flow statements like if.
Put a procedure around it and it will work.

You can use prepared statements
IF (#row <1) THEN
SET #lSQL = "ALTER TABLE tblname ADD colname INT";
PREPARE stmt FROM #lSQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
Hope it helps.

Related

Error Executing This Mysql Sp For Make Refresh Of The Fields Saved In Log Table Through Trigger But I Don't See The Error

This sp generate this Error but when I get the #queryString value and execute it, It's working:
Query 1 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 'CREATE TRIGGER triggers_after_insert AFTER INSERT ON mydb.mytable F' at line 2
This error is generated when I execute:
CALL prcTriggersLogsRefreshFields('mydb','mytable','myidtable');
This is the code:
DROP PROCEDURE "prcTriggersLogsRefreshFields";
CREATE PROCEDURE "prcTriggersLogsRefreshFields"(
par_dbName text,
par_tableName text,
par_keyField text
)
BEGIN
SET #strJsonObj = null;
SET #change_object = par_dbName||'.'||par_tableName;
SELECT GROUP_CONCAT('\'',COLUMN_NAME, '\',', COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = par_dbName AND TABLE_NAME = par_tableName INTO #strJsonObj;
SET #queryString = 'DROP TRIGGER `triggers_after_insert`;
CREATE TRIGGER `triggers_after_insert` AFTER INSERT ON `'||par_dbName||'`.`'||par_tableName||'` FOR EACH ROW BEGIN
SELECT JSON_ARRAYAGG(JSON_OBJECT('||#strJsonObj||')) change_obj FROM `'||par_dbName||'`.`'||par_tableName||'` WHERE '||par_keyField||'=New.'||par_keyField||' INTO #jsonRow;
INSERT INTO mylog_db.table_log (`change_id`, `change_date`, `db_name`, `table_name`, `change_object`, `change_event_name`, `previous_content`, `change_content`, `change_user`) VALUES (DEFAULT, NOW(), '''||par_dbName||''', '''||par_tableName||''', '''||#change_object||''', \'insert\', \'{}\', #jsonRow, New.user_created);
END;';
-- select #queryString;
PREPARE stmt FROM #queryString;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html says:
SQL syntax for prepared statements does not support multi-statements (that is, multiple statements within a single string separated by ; characters).
You have to run the statements one at a time if you use PREPARE.
There's no need to include the DROP TRIGGER in your prepared statement. You can run the DROP TRIGGER without prepare & execute, since there is no dynamic part in it. Then format the CREATE TRIGGER as a single statement and prepare and execute it.

MariaDB: How to store a Table name into a variable?

I need to use multiple times a table name into a query. To avoid repeating it I want to store the name into a User-Defined Variable.
What is wrong with this query?
SET #tableName := 'de-Table'
SELECT * FROM #tableName;
In MariaDB the error is cryptic and (as usual) doesn't help at all:
/* SQL Error (1064): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SELECT * FROM #tableName' at line 3 */
Thank you in advance
You need to use dynamic MySQL if you want a variable to be the table name. The following should work, if you're doing this directly from MySQL:
SET #tableName = 'de-Table';
SET #query = CONCAT('SELECT * FROM ', #tableName);
PREPARE stmt FROM #query;
EXECUTE stmt;

MySQL Stored Procedure with Prepared Statement does not work

I have the following stored procedure:
CREATE PROCEDURE getLastValueAutomaticShelter(IN fieldName varchar(30), position_number INT)
BEGIN
SET #query = CONCAT('SELECT * FROM automatic_changes WHERE',fieldName,'IS NOT NULL AND P_id=?');
PREPARE stmt FROM #query;
SET #position_number=position_number;
EXECUTE stmt USING #position_number;
DEALLOCATE PREPARE stmt;
END
Then I am running it:
mysql> call getLastValueAutomaticShelter('current_level', 500)//
And getting the following 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 'NOT N
ULL AND P_id=?' at line 1
Any ideas? Thanks.
You need to add some spaces in there:
SET #query = CONCAT('SELECT * FROM automatic_changes WHERE ',fieldName,' IS NOT NULL AND P_id=?');
/* right ^ here....and ^ here*/
Otherwise your final query might look like this:
SELECT * FROM automatic_changes WHEREcolumnameIS NOT NULL AND P_id='whatever';
You get the idea :)

MySQL 'Group' syntax error when no Group statement?

I'm trying to run the below script against MySQL server but I get the error:
ERROR 1064 (42000) at line 28: 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 'Group' at line 1
Here's the sql script:
/* Remove old indexes */
USE production;
DROP PROCEDURE IF EXISTS DropIndexes;
DELIMITER //
CREATE PROCEDURE DropIndexes()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE tbl, idx VARCHAR(1000);
DECLARE index_cursor CURSOR FOR SELECT TABLE_NAME, INDEX_NAME FROM information_schema.statistics WHERE table_schema = 'production' AND INDEX_NAME LIKE 'ix_%';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN index_cursor;
read_loop: LOOP
FETCH index_cursor INTO tbl, idx;
IF done THEN
LEAVE read_loop;
END IF;
SET #s = CONCAT('DROP INDEX ',idx,' ON ',tbl);
PREPARE stmt1 FROM #s;
EXECUTE stmt1;
DEALLOCATE PREPARE stmt1;
END LOOP;
CLOSE index_cursor;
END//
DELIMITER ;
CALL DropIndexes();
DROP PROCEDURE IF EXISTS DropIndexes;
Given the error makes no sense with no 'Group' statement I have no idea what the problem is.
Maybe you have an index or table named group. You need to escape reserved words like group with backticks. Try
SET #s = CONCAT('DROP INDEX `',idx,'` ON `',tbl,'`');
It must be your Table name selected from the statistics table. To get it accepted enclose it in back-ticks. And though not required on your index name ( because it starts with ix_ ), better you practice using the back-ticks.
SET #s = CONCAT( 'DROP INDEX `' , idx, '` ON `', tbl, '`' );

MySQL ALTER TABLE with arguments in stored procedure

In a MySQL migration script, I'm trying to drop all the foreign keys of a table without knowing the name of the constraints themselves. I need this because I can only be aware of the constraints names in a particular database installation, but the script has to work also in other installations where the name is unknown at current script coding time.
Here is my first guess of a stored procedure, but it doesn't work. In particular it complains about the '?' in ALTER TABLE.
DELIMITER $$
DROP PROCEDURE IF EXISTS drop_foreign_key_documents $$
CREATE PROCEDURE drop_foreign_key_documents ( )
BEGIN
WHILE (SELECT COUNT(*) AS index_exists FROM `information_schema`.`TABLE_CONSTRAINTS` c WHERE `c`.`CONSTRAINT_TYPE` LIKE '%FOREIGN%' AND `c`.`TABLE_NAME`='documents' and `c`.`TABLE_SCHEMA`='mydb') > 0 DO
SET #ctype = '%FOREIGN%';
SET #tname = 'documents';
SET #dbname = 'mydb';
SET #n = 'select `CONSTRAINT_NAME` INTO #cname FROM `information_schema`.`TABLE_CONSTRAINTS` c WHERE `c`.`CONSTRAINT_TYPE` LIKE ? AND `c`.`TABLE_NAME`=? and `c`.`TABLE_SCHEMA`=? LIMIT 0,1';
PREPARE stmt FROM #n;
EXECUTE stmt USING #ctype,#tname,#dbname;
SELECT #cname;
SET #s = 'ALTER TABLE `documents` DROP FOREIGN KEY ?';
PREPARE stmtd FROM #s;
EXECUTE stmtd USING #cname;
END WHILE;
END $$
DELIMITER ;
CALL drop_foreign_key_documents;
The output of MySQL is:
#cname
documents_ibfk_13
ERROR 1064 (42000) at line 23: 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 '?' at line 1
Now I can imagine why it complains: the ALTER TABLE statement cannot use '?' because the constraint name is not part of a WHERE clause and so it cannot be replaced by a positional parameter. What I don't know is how to build a parametrized ALTER TABLE statement.
Obvious answer:
SET #s = CONCAT('ALTER TABLE `documents` DROP FOREIGN KEY ', #cname);
PREPARE stmtd FROM #s;
EXECUTE stmtd;