Want to truncate a table if it exists:
IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'mytable') TRUNCATE mytable
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 'IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE
TABLE_NAME = 'mytable') ' at line 1
I tried also to add THEN after ) but the problems seems to be at IF.
You need the two statements below to do that:
create table if not exists <mytable>;
truncate table <mytable>;
So I had a similar issue, and to resolve it, I created this procedure:
DELIMITER $$
DROP PROCEDURE IF EXISTS `truncate_if_exist`$$
CREATE PROCEDURE `truncate_if_exist`(IN tbl_name VARCHAR(150) )
BEGIN
IF EXISTS( SELECT 1 FROM information_schema.TABLES WHERE table_name = tbl_name AND table_schema = DATABASE()) THEN
SET #query = CONCAT('TRUNCATE ', tbl_name);
PREPARE stmt FROM #query;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END IF;
END $$
DELIMITER ;
And then called it for each table that I wanted to truncate
for example:
CALL truncate_if_exist('users');
CALL truncate_if_exist('random_tmp_table');
Obviously, if the table does not exist, it will not run the TRUNCATE command.
Related
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
I am trying to create a database with some data not all. I don't need 1M+ records to do what I need so I am okay with only 10000 rows.
I figured I can use a stored procedure to loop through all the table and manually create each table and insert only 10000 rows.
I created a stored procedure like this
CREATE DEFINER=`root`#`10.%` PROCEDURE `createNewDatabase`(in db_name varchar(100), in new_db_name varchar(100))
BEGIN
DECLARE finish INT DEFAULT 0;
DECLARE tbl VARCHAR(100);
DECLARE cur_tables CURSOR FOR SELECT table_name FROM information_schema.tables WHERE table_schema = db_name AND TABLE_TYPE='BASE TABLE';
DECLARE CONTINUE HANDLER FOR NOT FOUND SET finish = 1;
OPEN cur_tables;
my_loop: LOOP
FETCH cur_tables INTO tbl;
IF finish = 1 THEN
LEAVE my_loop;
END IF;
SET #str = CONCAT('DROP TABLE IF EXISTS `', new_db_name, '`.`' , tbl , '`; CREATE TABLE `', new_db_name, '`.`' , tbl , '` LIKE `', db_name , '`.`', tbl,'`; INSERT INTO `', new_db_name , '`.`' , tbl, '` SELECT * FROM `', db_name ,'`.`', tbl , '` LIMIT 10000;');
PREPARE stmt FROM #str;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE cur_tables;
END
Then I called it like this
CALL createNewDatabase('baseTable', 'newTable');
But I run the procedure I get the following error
Error Code: 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 'CREATE TABLE `newTable`.`account_addresses` LIKE `baseTable`.`account_addres' at line 1
if I added the following 2 lines after just before the prepare statement
SELECT #str;
LEAVE my_loop;
I get the following queries which works if I executed them manually
DROP TABLE IF EXISTS `newTable`.`account_addresses`;
CREATE TABLE `newTable`.`account_addresses` LIKE `baseTable`.`account_addresses`;
INSERT INTO `newTable`.`account_addresses` SELECT * FROM `newTable`.`account_addresses` LIMIT 10000;
CREATE TABLE `newTable`.`account_addresses` LIKE `baseTable`.`account_addresses`; INSERT INTO `newTable`.`account_addresses` SELECT * FROM `baseTable`.`account_addresses` LIMIT 10000;
What am I doing wrong here? Why it is erroring?
Quote from mysql's documentation on PREPARE:
The text must represent a single statement, not multiple statements.
You are trying to execute a drop table and a create table statement, insert records in 1 prepared statement and this is not allowed. Have 3 separate prepared statement for the 3 commands.
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.
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, '`' );
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'email_subscription' AND COLUMN_NAME = 'subscribe_all')
THEN
ALTER TABLE email_subscription
ADD COLUMN subscribe_all TINYINT(1) DEFAULT 1,
ADD COLUMN subscribe_category varchar(512) DEFAULT NULL;
I had a look at huge amount of examples. but this query doesn't work, I got error of:
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 'IF NOT EXISTS (SELECT * FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME =' at line 1
If your host doesn't give you permission to create or run procedures, I think I found another way to do this using PREPARE/EXECUTE and querying the schema:
SET #s = (SELECT IF(
(SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'table_name'
AND table_schema = DATABASE()
AND column_name = 'col_name'
) > 0,
"SELECT 1",
"ALTER TABLE table_name ADD col_name VARCHAR(100)"
));
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
you can create a procedure for the query,
DELIMITER $$
CREATE PROCEDURE Alter_Table()
BEGIN
DECLARE _count INT;
SET _count = ( SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'email_subscription' AND
COLUMN_NAME = 'subscribe_all');
IF _count = 0 THEN
ALTER TABLE email_subscription
ADD COLUMN subscribe_all TINYINT(1) DEFAULT 1,
ADD COLUMN subscribe_category varchar(512) DEFAULT NULL;
END IF;
END $$
DELIMITER ;
There is no equivalent syntax to achieve this in a single MySQL statement.
To get something simlilar, you can either
1) attempt to add the column with an ALTER TABLE, and let MySQL raise an error if a column of that name already exists in the table, or
2) query the information_schema.columns view to check if a column of that name exists in the table.
Note that you really do need to check for the table_schema, as well as the table_name:
SELECT column_name
FROM information_schema.columns
WHERE table_schema = 'foo'
AND table_name = 'email_subscription'
AND column_name = 'subscribe_all'
and based on that, decide whether to run the ALTER TABLE
You are using MS SQL Server syntax in MySQL.
Also add condition for database name to check column existance.
Try this:
DELIMITER $$
CREATE PROCEDURE sp_AlterTable()
BEGIN
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dbName' AND
TABLE_NAME = 'email_subscription' AND
COLUMN_NAME = 'subscribe_all') THEN
ALTER TABLE email_subscription
ADD COLUMN subscribe_all TINYINT(1) DEFAULT 1,
ADD COLUMN subscribe_category VARCHAR(512) DEFAULT NULL;
END IF;
END $$
DELIMITER ;
SET #s = (SELECT IF(
(SELECT COUNT(column_name)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'oc_bitcoin_wallets_receive'
AND table_schema = 'k_opencart2'
AND column_name = 'test3'
) > 0,
"SELECT 1",
"ALTER TABLE `oc_bitcoin_wallets_receive` ADD COLUMN `test3` INT NOT NULL AFTER `test2`;"
));
PREPARE stmt FROM #s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Values for edit:
oc_bitcoin_wallets_receive - table name,
k_opencart2 - database name,
test3 - name of new column,
oc_bitcoin_wallets_receive - second location table
test3 - second location column,
test2 - name of column before new column.