Create temporary table in procedure, MySql - mysql

I need create a simple procedure, but after create a temporary table, mysql wants put 'end' after semicolon.
CREATE procedure zad2()
begin
drop temporary table if exists temp;
create temporary table temp as (select table_name, column_name
from information_schema.columns where table_schema = 'lista3' and table_name not like 'lista');
declare i int default 0;
end$$

SQL Stored procedure have a block where you will put all code/logic .. and that block is BEGIN and END , if you have an opening block which is BEGIN , you need to close it with END, that's why MySql wants you to put END after semi colon.
Below link can help with the syntax:
CREATE PROCEDURE and CREATE FUNCTION Syntax

I think that what is missing is to declare the DELIMITER $$ at the start of the statement:
DELIMITER $$ /*To tell MySQL that your delimiter is now '$$' */
CREATE procedure zad2()
begin
drop temporary table if exists temp;
create temporary table temp as (select table_name, column_name
from information_schema.columns where table_schema = 'lista3' and table_name not like 'lista');
declare i int default 0;
end$$
DELIMITER ; /*To tell your MySQL that you delimiter is back ';' */

Related

Error 1064 (42000) on create procedure MySQL

I'm having this specific error when trying to create a stored procedure on MySQL database:
CREATE PROCEDURE GET_COLUMNS(TABLENAME VARCHAR(50))
BEGIN
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'SolarTV' AND TABLE_NAME=TABLENAME;
END
All you should need to do here is temporarily change the delimiter while defining the procedure, then set it back to ; after the procedure has been created. Otherwise it'll get confused when it sees the first ; from within the procedure definition. Example:
DELIMITER //
CREATE PROCEDURE GET_COLUMNS(TABLENAME VARCHAR(50))
BEGIN
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'SolarTV' AND TABLE_NAME=TABLENAME;
END//
DELIMITER ;

Loop through array in mysql Stored procs

I need to dynamically alter set of tables
Currently i can alter only one using below SP.
DROP PROCEDURE IF EXISTS add_version_to_actor;
DELIMITER $$
CREATE DEFINER=CURRENT_USER PROCEDURE add_version_to_actor (IN table_name VARCHAR(40) )
BEGIN
DECLARE colName TEXT;
SELECT column_name INTO colName
FROM information_schema.columns
WHERE table_schema = 'database_name'
AND table_name = table_name
AND column_name = 'column';
IF colName is null THEN
Alter Table database_name.table_name ADD `sequence` INT( 10 ) NOT NULL;
END IF;
END$$
DELIMITER ;
CALL add_version_to_actor('table1');
DROP PROCEDURE add_version_to_actor;
Currently 'table1' is a single parameter. I need to pass multiple table names as string like this CALL add_version_to_actor('table1','table2');and loop through all of them.How can this be achieved.
Thanks in advance.

MySQL IF THEN condition to Drop a table

I am trying to use stored procedure and check on a particular table and use IF THEN condition to drop the table. Is it possible to issue the DROP statement in the conditional block?
delimiter $$
CREATE PROCEDURE FC_SQLF()
BEGIN
DECLARE SQLFOUND int;
SET #SQLFOUND = (select count(table_name) from information_schema.tables where table_schema = 'testdb' and table_name = 'temp_table');
IF #SQLFOUND = 1 THEN DROP TABLE testdb.abcd;
END IF;
END $$

check if column exists before ALTER TABLE -- mysql

Is there a way to check if a column exists in a mySQL DB prior to (or as) the ALTER TABLE ADD coumn_name statement runs? Sort of an IF column DOES NOT EXIST ALTER TABLE thing.
I've tried ALTER IGNORE TABLE my_table ADD my_column but this still throws the error if the column I'm adding already exists.
EDIT: use case is to upgrade a table in an already installed web app-- so to keep things simple, I want to make sure the columns I need exist, and if they don't, add them using ALTER TABLE
Since mysql control statements (e.g. "IF") only work in stored procedures, a temporary one can be created and executed:
DROP PROCEDURE IF EXISTS add_version_to_actor;
DELIMITER $$
CREATE DEFINER=CURRENT_USER PROCEDURE add_version_to_actor ( )
BEGIN
DECLARE colName TEXT;
SELECT column_name INTO colName
FROM information_schema.columns
WHERE table_schema = 'connjur'
AND table_name = 'actor'
AND column_name = 'version';
IF colName is null THEN
ALTER TABLE actor ADD version TINYINT NOT NULL DEFAULT '1' COMMENT 'code version of actor when stored';
END IF;
END$$
DELIMITER ;
CALL add_version_to_actor;
DROP PROCEDURE add_version_to_actor;
Do you think you can try this?:
SELECT IFNULL(column_name, '') INTO #colName
FROM information_schema.columns
WHERE table_name = 'my_table'
AND column_name = 'my_column';
IF #colName = '' THEN
-- ALTER COMMAND GOES HERE --
END IF;
It's no one-liner, but can you at least see if it will work for you? At least while waiting for a better solution..
Utility functions and procedures
First, I have a set of utility functions and procedures that I use to do things like drop foreign keys, normal keys and columns. I just leave them in the database so I can use them as needed.
Here they are.
delimiter $$
create function column_exists(ptable text, pcolumn text)
returns bool
reads sql data
begin
declare result bool;
select
count(*)
into
result
from
information_schema.columns
where
`table_schema` = 'my_database' and
`table_name` = ptable and
`column_name` = pcolumn;
return result;
end $$
create function constraint_exists(ptable text, pconstraint text)
returns bool
reads sql data
begin
declare result bool;
select
count(*)
into
result
from
information_schema.table_constraints
where
`constraint_schema` = 'my_database' and
`table_schema` = 'my_database' and
`table_name` = ptable and
`constraint_name` = pconstraint;
return result;
end $$
create procedure drop_fk_if_exists(ptable text, pconstraint text)
begin
if constraint_exists(ptable, pconstraint) then
set #stat = concat('alter table ', ptable, ' drop foreign key ', pconstraint);
prepare pstat from #stat;
execute pstat;
end if;
end $$
create procedure drop_key_if_exists(ptable text, pconstraint text)
begin
if constraint_exists(ptable, pconstraint) then
set #stat = concat('alter table ', ptable, ' drop key ', pconstraint);
prepare pstat from #stat;
execute pstat;
end if;
end $$
create procedure drop_column_if_exists(ptable text, pcolumn text)
begin
if column_exists(ptable, pcolumn) then
set #stat = concat('alter table ', ptable, ' drop column ', pcolumn);
prepare pstat from #stat;
execute pstat;
end if;
end $$
delimiter ;
Dropping constraints and columns using the utilities above
With those in place, it is pretty easy to use them to check columns and constraints for existence:
-- Drop service.component_id
call drop_fk_if_exists('service', 'fk_service_1');
call drop_key_if_exists('service', 'component_id');
call drop_column_if_exists('service', 'component_id');
-- Drop commit.component_id
call drop_fk_if_exists('commit', 'commit_ibfk_1');
call drop_key_if_exists('commit', 'commit_idx1');
call drop_column_if_exists('commit', 'component_id');
-- Drop component.application_id
call drop_fk_if_exists('component', 'fk_component_1');
call drop_key_if_exists('component', 'application_id');
call drop_column_if_exists('component', 'application_id');
Make a count sentence with the example below by John Watson.
SELECT count(*) FROM information_schema.COLUMNS
WHERE COLUMN_NAME = '...'
and TABLE_NAME = '...'
and TABLE_SCHEMA = '...'
Save that result in an integer and then make it a condition to apply the ADD COLUMN sentence.
You can test if a column exists with:
IF EXISTS (
SELECT * FROM information_schema.COLUMNS
WHERE COLUMN_NAME = '...'
and TABLE_NAME = '...'
and TABLE_SCHEMA = '...')
...
Just fill in your column name, table name, and database name.
Although its quite an old post but still i feel good about sharing my solution to this issue. If column doesn't exist then an exception would occur definitely and then i am creating the column in table.
I just used the code below:
try
{
DATABASE_QUERY="SELECT gender from USER;";
db.rawQuery(DATABASE_QUERY, null);
}
catch (Exception e)
{
e.printStackTrace();
DATABASE_UPGRADE="alter table USER ADD COLUMN gender VARCHAR(10) DEFAULT 0;";
db.execSQL(DATABASE_UPGRADE);
}
You can create a procedure with a CONTINUE handler in case the column exists (please note this code doesn't work in PHPMyAdmin):
DROP PROCEDURE IF EXISTS foo;
CREATE PROCEDURE foo() BEGIN
DECLARE CONTINUE HANDLER FOR 1060 BEGIN END;
ALTER TABLE `tableName` ADD `columnName` int(10) NULL AFTER `otherColumn`;
END;
CALL foo();
DROP PROCEDURE foo;
This code should not raise any error in case the column already exists. It will just do nothing and carry on executing the rest of the SQL.
DELIMITER $$
DROP PROCEDURE IF EXISTS `addcol` $$
CREATE DEFINER=`admin`#`localhost` PROCEDURE `addcol`(tbn varchar(45), cn varchar(45), ct varchar(45))
BEGIN
#tbn: table name, cn: column name, ct: column type
DECLARE CONTINUE HANDLER FOR 1060 BEGIN END;
set cn = REPLACE(cn, ' ','_');
set #a = '';
set #a = CONCAT("ALTER TABLE `", tbn ,"` ADD column `", cn ,"` ", ct);
PREPARE stmt FROM #a;
EXECUTE stmt;
END $$
DELIMITER ;
This syntax work for me :
SHOW COLUMNS FROM < tablename > LIKE '< columnName >'
More in this post :
https://mzulkamal.com/blog/mysql-5-7-check-if-column-exist?viewmode=0
As per MYSQL Community:
IGNORE is a MySQL extension to standard SQL. It controls how ALTER TABLE works if there are duplicates on unique keys in the new table or if warnings occur when strict mode is enabled. If IGNORE is not specified, the copy is aborted and rolled back if duplicate-key errors occur. If IGNORE is specified, only one row is used of rows with duplicates on a unique key. The other conflicting rows are deleted. Incorrect values are truncated to the closest matching acceptable value.
So a working Code is:
ALTER IGNORE TABLE CLIENTS ADD CLIENT_NOTES TEXT DEFAULT NULL;
Data posted here:
http://dev.mysql.com/doc/refman/5.1/en/alter-table.html

Stored Procedure with ALTER TABLE

I have a need to sync auto_increment fields between two tables in different databases on the same MySQL server. The hope was to create a stored procedure where the permissions of the admin would let the web user run ALTER TABLE [db1].[table] AUTO_INCREMENT = [num]; without giving it permissions (That just smells of SQL injection).
My problem is I'm receiving errors when creating the store procedure. Is this something that is not allowed by MySQL?
DROP PROCEDURE IF EXISTS sync_auto_increment;
CREATE PROCEDURE set_auto_increment (tableName VARCHAR(64), inc INT)
BEGIN
ALTER TABLE tableName AUTO_INCREMENT = inc;
END;
To extend on the discussion on the comments on Chibu's answer... yes, you can use prepared statements. But you got to use CONCAT to create the sentence instead of using PREPARE ... FROM ....
Here is a working solution:
DROP PROCEDURE IF EXISTS set_auto_increment;
DELIMITER //
CREATE PROCEDURE set_auto_increment (_table VARCHAR(64), _inc INT)
BEGIN
DECLARE _stmt VARCHAR(1024);
SET #SQL := CONCAT('ALTER TABLE ', _table, ' AUTO_INCREMENT = ', _inc);
PREPARE _stmt FROM #SQL;
EXECUTE _stmt;
DEALLOCATE PREPARE _stmt;
END//
DELIMITER;
I've learned this form the article Prepared Statement Failure by Michael McLaughlin.
The problem seems to be that you need to change the delimiter. It thinks that the Alter table line is the end of the function. Try this:
DROP PROCEDURE IF EXISTS sync_auto_increment;
DELIMITER //
CREATE PROCEDURE set_auto_increment (tableName VARCHAR(64), inc INT)
BEGIN
ALTER TABLE tableName AUTO_INCREMENT = inc;
END//
DELIMITER ;
Sometimes mysql is still picky about letting you use stored procedures, so you can do try this if you still can't run it:
DROP PROCEDURE IF EXISTS sync_auto_increment;
DELIMITER //
CREATE PROCEDURE set_auto_increment (tableName VARCHAR(64), inc INT)
DETERMINISTIC
READS SQL DATA
BEGIN
ALTER TABLE tableName AUTO_INCREMENT = inc;
END//
DELIMITER ;
I think you'll find you can't put Data Definition Language statements into a stored procedure. A possible exception would be CREATE TEMPORARY TABLE. I have searched the MySQL manual for more information on that point; it says the stored procedure may contain a statement_list, but nowhere defines what that means. But I think that's the case.