Teradata rename table if exists - rename

I'm using Teradata. I'd like rename a table with a script sql and not using bteq, if a specific conditions is satisfied.
In particular:
if TABLE_A exists => rename table TABLE_B to TABLE_B_OLD
In Sql Server:
IF OBJECT_ID('TABLE_A', 'U') IS NULL
EXEC sp_rename 'TABLE_B', 'TABLE_B_OLD';
In Oracle:
DECLARE
cnt NUMBER;
BEGIN
select COUNT(*) INTO cnt from sys.user_tables where table_name = 'TABLE_A'
IF cnt>0 THEN
execute immediate 'rename table TABLE_B to TABLE_B_OLD';
END IF;
END;
How can I made it with Teradata,
Thanks
Fabio

How about this?
REPLACE PROCEDURE IF_EXISTS_RENAME
(
IN table_name VARCHAR(30),
IN new_table_name VARCHAR(30)
)
BEGIN
IF EXISTS(SELECT 1 FROM dbc.tables WHERE 1=1 AND tablename = table_name and databasename=DATABASE) THEN
CALL DBC.SysExecSQL('RENAME TABLE ' || table_name ||' to '|| new_table_name);
END IF;
END;

Changed code provided by #access_granted to include Database Name as variable
REPLACE PROCEDURE FAR.RENAME_TABLE
(
IN table_name VARCHAR(30),
IN new_table_name VARCHAR(30),
IN db_name VARCHAR(50)
)
BEGIN
declare my_sql VARCHAR(1000);
IF EXISTS(SELECT 1
FROM dbc.tables
WHERE 1=1 AND tablename = table_name and databasename= db_name)
THEN
set my_sql ='RENAME TABLE ' || table_name ||' to '|| new_table_name||';' ;
EXECUTE IMMEDIATE my_sql;
END IF;
END;
Calling the procedure with three arguments:
Old Table Name
New Table Name
Database Name
call FAR.RENAME_TABLE('TEST_ABC','TEST_11','FAR')

Assuming you're on a relatively modern version of Teradata, you can do this in SQL Assistant (or BTEQ):
select
count (*)
from
dbc.tablesv where tablename = '<your table>'
and databasename = '<your db>'
having count (*) > 0;
.if activitycount = 1 then .GOTO RenameTable;
.if activitycount <> 1 then .quit;
.LABEL RenameTable
rename table <your table> <your new name;

Related

I wrote a function to break a string into parts delimitted by $ Now I need to access it with select from but getting error

I have created following function to split a given string delimited by $.
I want to call the function as part of SQL query and get the result as rows.
CREATE OR REPLACE FUNCTION string_tokenize2
( p_string IN CLOB
-- p_delim in varchar2
)
RETURN SYS_REFCURSOR
AS
cur1 SYS_REFCURSOR;
BEGIN
OPEN cur1 FOR
SELECT regexp_substr(p_string
,'[^$]+'
,1
,LEVEL) AS str
FROM sys.dual
CONNECT BY LEVEL <= regexp_count(p_string
,'\$') + 1;
RETURN cur1;
END string_tokenize2;
/
However when I tried it using in a SQL resulted in following error.
Kindly assist me how to proceed here ,
select string_tokenize2('')from dual;
put your IN variable in the ( )
Do you have any constraint to stick to the function as it is ? OR
Why not create an object type and change the function to return a table type and then use it in SQL ?
--create the type
CREATE OR REPLACE TYPE string_tokenize2_obj IS TABLE OF VARCHAR2(4000);
--Function changes
CREATE OR REPLACE FUNCTION string_tokenize2(p_string IN CLOB)
RETURN string_tokenize2_obj AS
l_tab string_tokenize2_obj;
BEGIN
SELECT to_char(str)
BULK COLLECT
INTO l_tab
FROM (SELECT regexp_substr(p_string
,'[^$]+'
,1
,LEVEL) str
FROM dual
CONNECT BY LEVEL <= regexp_count(p_string
,'\$') + 1);
RETURN l_tab;
END string_tokenize2;
/
SQL> SELECT column_value str FROM TABLE(string_tokenize2('abc$def$geh$ijkl'));
STR
--------------------------------------------------------------------------------
abc
def
geh
ijkl
SQL>
You can either
1) use xmltable and xmltype to read data from sys_refcursor functions results if you need that data in select statement:
ie you can use the same your function without any changes, but read it using xmltable+xmltype:
select *
from xmltable(
'/ROWSET/ROW'
passing xmltype(string_tokenize2('1$2$3$4'))
columns
str varchar2(100) path 'STR'
);
Results:
STR
---------------------------------------
1
2
3
4
2) or use plsql implicit results if you are just need to get data from any client: https://oracle-base.com/articles/12c/implicit-statement-results-12cr1
Example:
CREATE OR REPLACE PROCEDURE string_tokenize2
( p_string IN CLOB
-- p_delim in varchar2
)
AS
cur1 SYS_REFCURSOR;
BEGIN
OPEN cur1 FOR
SELECT regexp_substr(p_string
,'[^$]+'
,1
,LEVEL) AS str
FROM sys.dual
CONNECT BY LEVEL <= regexp_count(p_string
,'\$') + 1;
DBMS_SQL.RETURN_RESULT(cur1);
END string_tokenize2;
/
begin
string_tokenize2('1,2,3,4');
end;
Result:
SQL> exec string_tokenize2('1,2,3,4');
ResultSet #1
STR
---------------------------------------
1,2,3,4
3) or just return sys_refcursor to client app as a bind variable for fetching:
begin
:res := string_tokenize2('1,2,3,4');
end;
Example in sql*plus:
SQL> var res refcursor
SQL> exec :res := string_tokenize2('1$2$3$4');
SQL> print res
STR
--------------------
1
2
3
4
4) Or varchar2 collections/varrays as suggested by other users

Query and get all database names and subquery especific tables from all databases

I have different databases. I have tables within each database.
I would like to know if I can ask how many databases excluding some such as 'schema' 'mysql' I have once know how to perform a subquery asked by a particular table of all the databases resulting from the first question.
example.
the structure would be
db1 -> user-> id,name,imei,telephone,etc..
db2 -> user-> id,nameuser,imei,telephone,etc..
db3 -> user-> id,nameuser,imei,telephone,etc..
....
db1000 -> user-> id,nameuser,imei,telephone,etc..
the query are how this, but this get error
SELECT CONCAT('SELECT * FROM ' schema_name 'where imei.'schema_name = nameimai)
FROM information_schema.schemata
WHERE schema_name NOT IN ('information_schema','mysql','performance_schema','sys','performance_schema','phpmyadmin');
Results
name db id name imei phone
---------- ---------- ---------- ---------- ----------
db1 1 John 76876876 xxx
db2 2300 John 76876876 xxxx
...
db1000 45 John 76876876 xxx
its possible in one query
thanks..
Here's one way you could do it with a stored procedure.
If I understand correctly, you have multiple databases with identical tables (user) and you want to run a query against all these tables for a specific value.
I've made this fairly general so that you can pass in the table name and also the where clause. Your example seemed to be looking for user records with imei = '76876876', so if we use that example.
USE test;
DELIMITER //
DROP PROCEDURE IF EXISTS multidb_select //
-- escape any quotes in the query string
-- call multidb_select ('usertest','WHERE imei = \'76876876\'')
CREATE PROCEDURE multidb_select(IN tname VARCHAR(64), IN qwhere VARCHAR(1024))
READS SQL DATA
BEGIN
DECLARE vtable_schema VARCHAR(64);
DECLARE vtable_name VARCHAR(64);
DECLARE done BOOLEAN DEFAULT FALSE;
-- exclude views and system tables
DECLARE cur1 CURSOR FOR
SELECT `table_schema`, `table_name`
FROM `information_schema`.`tables`
WHERE `table_name` = tname
AND `table_type` = 'BASE TABLE'
AND `table_schema` NOT IN
('information_schema','mysql','performance_schema',
'sys','performance_schema','phpmyadmin')
ORDER BY `table_schema` ASC;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done := TRUE;
OPEN cur1;
SET #unionall := '';
read_loop: LOOP
FETCH cur1 INTO vtable_schema, vtable_name;
IF done THEN
LEAVE read_loop;
END IF;
-- UNION ALL in case the id is the same
IF CHAR_LENGTH(#unionall) = 0 THEN
SET #unionall =
CONCAT("SELECT \'", vtable_schema , "\' AS 'Db', t.* FROM `",
vtable_schema, "`.`" , vtable_name, "` t ", qwhere);
ELSE
SET #unionall =
CONCAT(#unionall, " UNION ALL SELECT \'", vtable_schema ,
"\' AS 'Db', t.* FROM `", vtable_schema,
"`.`", vtable_name, "` t ", qwhere);
END IF;
END LOOP;
CLOSE cur1;
PREPARE stmt FROM #unionall;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END //
DELIMITER ;
Run it with
call test.multidb_select('user','WHERE imei = \'76876876\'')

Insert the data into the remote table from # temp table in the stored procedure

I have a stored procedure in AZURE SQL database.In that there is a requirement to insert the records into the remote table from #temp table.
As xxxx_table is in the remote database used sp_execute_remote.
below is the scenario:
Create Procedure SP1 parameter1, Parameter2
As
select Distinct B.column1, B.Column2
into #A
from (Query1
Union
Query2) B
if (select count(1) from #A) > 0
Begin
Exec sp_execute_remote #data_source_name = N'Remotedatabase',
#stmt = N'INSERT INTO [dbo].[xxxx_table]
SELECT DISTINCT
'xxx' AS 'column1',
'xxx as 'Column2',
'xxx' AS 'Column3',
'xxx' AS 'Column4',
'xxx' AS Column4
FROM #A A INNER JOIN table1 on A.Column1 = Table1.Column2'
End
)
Getting the syntax error as below:
Incorrect syntax near 'xxx'.
Where am i going wrong? or let me know if there is another way to achieve this.
If you need to dynamically build a string in SQL single-quote the whole sentence, or use 'some text' + 'another text' to concat sentences. If you must add single quote use a double single quote ''
Example:
DECLARE #param1 int;
DECLARE #param1 VARCHAR(10);
SET #param1 = 10;
SET #param2 = 'CCDOS87'
#Stmt = 'SELECT Field1 FROM TableName WHERE Field1 = '
+ CAST(#param1 AS VARCHAR(100))
+ ' AND Field1 = '''
+ param2
+ ''''; <- This is a single '
#stmt = N'INSERT INTO [dbo].[Error_table]
SELECT DISTINCT
xxx AS column1,
xxx as Column2,
xxx AS Column3,
xxx AS Column4,
xxx AS Environment
FROM #A A INNER JOIN table1 on A.Column1 = Table1.Column2'
update
If your tables are in different databases but in the same server use:
INSERT INTO SERVER.SCHEMA.TABLE_NAME
SELECT Something
FROM SERVER.SCHEMA.TABLE_NAME

TSQL String modify

I have a problem with string.
I have a variable #Rights which looks like 'ASD,ZXC,QWE,IOP,JKL'
What I need to do is use this string in
SELECT * FROM dbo.Example
WHERE Rights IN (#Rights)
Problem is that I need to convert:
'ASD,ZXC,QWE,IOP,JKL'
to:
'ASD','ZXC','QWE','IOP','JKL'
How can I do this?
you can create a split function
CREATE FUNCTION [dbo].[Split]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
GO
and after you can convert the string in a temp table
DECLARE #Rights NVARCHAR(128)
SET #Rights = 'ASD,ZXC,QWE,IOP,JKL'
SELECT *
INTO #Temp
FROM dbo.Split(#Rights , ',')
and after you can use it in your query like this
SELECT * FROM dbo.Example
WHERE Rights IN (SELECT Data FROM #Temp)
You can try like this:
DECLARE #xml xml, #str varchar(100), #delimiter varchar(10)
SET #str = 'ASD,ZXC,QWE,IOP,JKL'
SET #delimiter = ','
SET #xml = cast(('<X>'+replace(#str, #delimiter, '</X><X>')+'</X>') as xml)
SELECT C.value('.', 'varchar(10)') as value FROM #xml.nodes('X') as X(C)
SQL DEMO
You can use Dynamic SQL:
LiveDemo
-- sample data
CREATE TABLE #Example(ID INT IDENTITY(1,1), Rights VARCHAR(100));
INSERT INTO #Example VALUES ('ASD'), ('ABC'), ('IOP');
DECLARE #Rights NVARCHAR(MAX) = 'ASD,ZXC,QWE,IOP,JKL';
DECLARE #sql NVARCHAR(MAX) =
N'SELECT *
FROM #Example
WHERE Rights IN (''<placeholder>'')';
SET #sql = REPLACE(#sql, '<placeholder>', REPLACE(#Rights, ',', ''','''));
-- SELECT #sql; -- for debug
EXEC dbo.sp_executesql
#sql;
But you should reconsider using Table Valued Parameter instead.

Dropping all tables in Sybase ASE including those with constraints

What is the best way to completely drop all tables in a database in Sybase ASE without dropping the database? I have been using a script: from this question but I am getting errors trying to drop all tables in a database due to referential integrity.
In MySQL I could use SET FOREIGN_KEY_CHECKS = 0
Is there a way to do this in Sybase ASE or can the script above be extended to loop through the constraints?
First you have to drop constraints:
declare cur cursor
for
select SOR.Name as constraint, SOT.Name as table
from sysreferences SR
join sysobjects SOR on SOR.id = SR.constrid
join sysconstraints SC on SC.constrid = SR.constrid
join sysobjects SOT on SOT.id = SC.tableid
go
declare #constraint varchar(500)
declare #table varchar(500)
declare #SQL varchar(500)
open cur
fetch cur into #constraint,#table
while (##sqlstatus = 0)
begin
select #SQL = 'alter table '+#table+' drop '+#constraint
exec( #SQL)
fetch cur into #constraint,#table
end
close cur
deallocate cursor cur
next you can drop tables.
The procedure to drop all constraints in the accepted answer did not work for me. Here is a modified version which works in my ASE16.
BEGIN
declare cur cursor
for
select o.name, t.name from sysreferences r
join sysobjects o on o.id = r.constrid
join sysconstraints c on c.constrid = r.constrid
join sysobjects t on t.id = c.tableid
END
GO
--
declare #constraint varchar(500)
declare #table varchar(500)
declare #SQL varchar(500)
--
open cur
fetch cur into #constraint,#table
while (##sqlstatus = 0)
begin
--
select #SQL = 'alter table '+#table+' drop constraint '+#constraint
exec( #SQL)
fetch cur into #constraint,#table
--
end
close cur
deallocate cursor cur
the above logic is correct but the query is wrong and you might get issues with the "constraint" and "table" keywords.
use something like constriantName and tableName in line 3
The query is missing "constraint", correct query:
'alter table ' + #table + ' drop constraint ' +#constraint

Resources