MySQL Backup Table if it Exists - sql

I am trying to write a script that will copy all the data in table a to table b if table a exists. Table b is the exact same structure as table a would be if it exists, though it may not. I am able to copy using the following statement: INSERT INTO 'B' SELECT * FROM 'A', but I don't know where to use IF EXISTS, or if I even can to determine if I an perform the insertion. I am trying to do this in SQL only as it will be run through as a .sql script from the command line.

MySQL only:
DROP PROCEDURE IF EXISTS myupdate;
DELIMITER //
CREATE PROCEDURE myupdate ()
BEGIN
DECLARE found VARCHAR(64);
SET found = (SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = Database() AND TABLE_NAME = 'A');
IF found = 'types' THEN
INSERT INTO B SELECT * FROM A;
SELECT 'A into B';
ELSE
SELECT 'A not found';
END IF;
END;//
DELIMITER ;
CALL myupdate();
DROP PROCEDURE myupdate;
Expand to you're liking comparing the column definition in INFORMATION_SCHEMA.COLUMNS for A & B if you need finer control.

I have accepted Wrikken's answer but am using this as my final code. I need to reuse the procedure he provided for multiple tables, so I modified it slightly. It makes the assumption that the backup table has already been created.
DROP PROCEDURE IF EXISTS tableUpdate;
DELIMITER //
CREATE PROCEDURE tableUpdate(name VARCHAR(32))
BEGIN
DECLARE cnt tinyint(1);
DECLARE btable VARCHAR(36);
SET btable = CONCAT(name,'BAK');
SET cnt = (SELECT COUNT(TABLE_NAME) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'TAA' AND TABLE_NAME = name);
IF cnt > 0 THEN
SET #q:= CONCAT('INSERT INTO ',CONCAT(btable,CONCAT(' SELECT * FROM ',name)));
PREPARE stmt FROM #q;
EXECUTE stmt;
COMMIT;
ELSE
SELECT 'No update necessary.';
END IF;
END;//
DELIMITER ;
CALL tableUpdate('A');
DROP PROCEDURE tableUpdate;

You can do so by performing the following:
select count(*) from my_tables where table_name='b';
If count>0 then
update b...;
else
create table b;
insert into my_tables(table_name) values('b');
insert into b...;
end if;

Related

Trying to query a redshift within SELECT statement

Current table1:
col1
-------------
schema.table1
schema.table2
schema.table3
Desired table1:
col1 col2
------------------------------------------------------------
schema.table1 value of (select count(*) from schema.table1)
schema.table2 value of (select count(*) from schema.table1)
schema.table3 value of (select count(*) from schema.table1)
It is not working, I tried using function too, but function doesn't allow to use 'FROM'
select col1, (select count(*) from col1)
from table1
I am trying to create this query in redshift. Can anyone please help me out?
To perform this task you will need a stored procedure AND a defined cursor. The stored procedure allows for looping and the cursor provides the ability to execute a newly created statement (dynamic querying).
For example:
Create the starting materials, 3 tables and a table that references these tables.
create table foo as (select 1 as A);
create table goo as (select 2 as A);
create table hoo as (select 3 as A);
create table tabs as (select 'foo' as tab union all select 'goo' union all select 'hoo');
Next define the stored procedure the will create the dynamic SQL
CREATE OR REPLACE procedure count_tabs(curs1 INOUT refcursor)
AS
$$
DECLARE
row record;
statement varchar := '';
union_needed BOOL := false;
BEGIN
for row in select tab from tabs LOOP
IF union_needed THEN
statement := statement || ' UNION ALL ';
END IF;
statement := statement || 'select \'' || row.tab || '\' as table_name, count(*) as table_count from ' || row.tab ;
union_needed := true;
END LOOP;
RAISE NOTICE 'sql to execute: %',statement;
open curs1 for execute statement;
END;
$$ LANGUAGE plpgsql;
Lastly we need to call the procedure and execute the cursor
call count_tabs('mycursor');
fetch 1000 from mycursor;
A few notes on this:
This assumes you want the results as output on your bench. If you want to create a table with the results this is doable in the same structure
Since the FROM clause value(s) is unknown at compile time this needs to be done in 2 steps - create the query and then execute the query.
I believe you can have the procedure walk this same cursor itself but doing this is exceptionally slow

snowflake: create or replace table when only a condition is met

I have a requirement to create or replace a table only if certain variable value is 1
SET variable = (select statement) -- $variable will be 1 or 0 depending on value returned from select statment
create or replace table2 as select * from table1 (only if $variable =1)
Is there any way to do it? If the variable value is 0, the create statement should be skipped
Using Snowflake Scripting block:
-- CREATE TABLE table1 AS SELECT 1 AS col;
SET variable = (SELECT 1);
BEGIN
IF ($variable = 1) THEN
create or replace table table2 as select * from table1;
END IF;
END;
Variable could be defined also at Snowflake Scripting block level:
DECLARE
variable INTEGER := (SELECT 1);
BEGIN
IF (:variable = 1) THEN
create or replace table table2 as select * from table1;
END IF;
END;

How to insert updated rows in a new table on DB2 - IBM

I need to create an update using sql dynamic and all the updated rows have to be sent in a log table.
In microsoft, i can use OUTPUT clause and it inserts the updated rows in a table, but how can i do this in db2, using sql dynamic?
I have the following tables:
AllCustomers - contains all customers from a db
Id
Name
1
John
2
Test
gdpr_id. - contains all customers which should be updated
Id
Name
1
John
gdpr_log - should contain the output of the update stmt
Id
Name
1
John
I found the below syntax , but it just displays the results.
SELECT fields FROM FINAL TABLE
(update table set field = 'value' where id ='xyz')
I tried to create another dynamic stmt as
INSERT INTO
SELECT fields FROM FINAL TABLE
(update table set field = 'value' where id ='xyz')
and the syntax is not recognized.
How can i replace it to insert all the updated values in a log table?
I have to use sql dynamic because the tables which need to be updated are stored in a metadata table and with a cursor, i create the update script for each line from the metadata table.
UPDATE:
Metadata table looks like this:
table
column
AllCustom
Name
AllCustom
Lastname
CREATE OR REPLACE PROCEDURE sp_test ()
DYNAMIC RESULT SETS 1
P1: BEGIN
--*****************VARIABLES *****************
DECLARE EOF INT DEFAULT 0;
declare v_table nvarchar(50);
declare v_column nvarchar(50);
declare v_rowid nvarchar(50);
declare v_stmt nvarchar(8000);
declare s1 statement;
--*****************UPDATE STEP *****************
-- Declare cursor
DECLARE cursor1 CURSOR WITH HOLD WITH RETURN FOR
SELECT table,column FROM metadata_tbl;
declare c1 cursor for s1;
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET EOF = 1;
OPEN cursor1;
WHILE EOF = 0 DO
FETCH FROM cursor1 INTO v_table,v_column;
SET v_stmt = 'WITH A AS
(
SELECT name
FROM FINAL TABLE
(
UPDATE ' || v_table || ' set ' || v_column || ' = ''some name'' where id in (select ID from gdpr_id )
)
)
SELECT COUNT (1) as tst
FROM FINAL TABLE
(
INSERT INTO GDPR_LOG (table,name, LOGDATE)
SELECT ''' || v_table || ''', name, current_timestamp from A
) B';
PREPARE s1 FROM v_stmt ;
open c1 using v_table,v_column;
close c1;
END WHILE;
CLOSE cursor1;
END P1
Update step works fine, insert step duplicates the rows inserted.
What should I do to have the insert step ok?
You have to use SELECT as an outermost statement and keep inner SELECTs in distinct CTEs, if you have a number of them.
Try this:
WITH A AS
(
SELECT ID, NAME
FROM FINAL TABLE
(
UPDATE GDPR
SET NAME = 'Some name'
WHERE ID = 1
)
)
SELECT COUNT (1)
FROM FINAL TABLE
(
INSERT INTO GDPR_LOG (ID, NAME)
SELECT * FROM A
) B
Update:
Using dynamic SQL.
You must enclose the whole statement with some statement termination character (say, #) different from the default one (;) if you use some tool to run this compound statement and specify this statement terminator correctly there.
BEGIN
DECLARE C1 CURSOR FOR S1;
PREPARE S1 FROM
'
WITH A AS
(
SELECT ID, NAME
FROM FINAL TABLE
(
UPDATE GDPR
SET NAME = ?
WHERE ID = ?
)
)
SELECT COUNT (1)
FROM FINAL TABLE
(
INSERT INTO GDPR_LOG (ID, NAME)
SELECT * FROM A
) B
';
OPEN C1 USING 'Name', 1;
CLOSE C1;
END

insert and update a table using cursor

I'm trying to insert records to table
input from information_schema :
select table_schema,table_name,table_type
from information_schema.tables
where table_schema = 'MYSCHEMA';
expected output:
insert into new table along with DDL of table_name
to get DDL: select get_ddl('table','INVOICING')
Can you help me?
create or replace procedure proc_getddl
is
v_tableschema varchar(30);
v_tablename varchar(30);
v_tabletype varchar(30);
v_getddl varchar(110);
cursor getddl is
select table_schema,table_name,table_type,get_ddl('table','INVOICING')
from information_schema.tables
where table_schema = 'MYSCHEMA';
begin
open getddl;
LOOP
fetch getddl into v_tableschema,v_tablename,v_tabletype,v_getddl;
EXIT WHEN getddl%NOTFOUND;
INSERT INTO backup_table
values (v_tableschema,v_tablename,v_tabletype,v_getddl);
END LOOP;
close getddl;
end proc_getddl;
I can use this but I want it to execute for all tables in information schema
Try something like
create table backup_table as
select table_schema,table_name,table_type,get_ddl('table','INVOICING')
from information_schema.tables
where table_schema = 'MYSCHEMA';
According to this https://sparkbyexamples.com/snowflake/snowflake-create-table-as-select/

In MySQL: How to pass a table name as stored procedure and/or function argument?

For instance, this does not work:
DELIMITER //
CREATE PROCEDURE countRows(tbl_name VARCHAR(40))
BEGIN
SELECT COUNT(*) as ct FROM tbl_name;
END //
DELIMITER ;
CALL countRows('my_table_name');
Produces:
ERROR 1146 (42S02): Table 'test.tbl_name' doesn't exist
However, this works as expected:
SELECT COUNT(*) as ct FROM my_table_name;
What syntax is required to use an argument as a table name in a select statement? Is this even possible?
Prepared statements are what you need.
CREATE PROCEDURE `test1`(IN tab_name VARCHAR(40) )
BEGIN
SET #t1 =CONCAT('SELECT * FROM ',tab_name );
PREPARE stmt3 FROM #t1;
EXECUTE stmt3;
DEALLOCATE PREPARE stmt3;
END $$
You can do it like this:
DROP PROCEDURE IF EXISTS `getDataUsingSiteCode`;
DELIMITER $$
CREATE PROCEDURE `getDataUsingSiteCode`(
IN tab_name VARCHAR(40),
IN site_ VARCHAR(255)
)
BEGIN
SET #site_code = site_;
SET #sql_ =CONCAT('SELECT * FROM ',tab_name,' WHERE site=?');
PREPARE statement_ FROM #sql_;
EXECUTE statement_ using #site_code;
END$$
DELIMITER ;