I need a to create an sql script which from a table table will build a dynamic sql request in the following way:
select ID || ',' || NAME || ',' || CODE
from TABLE_TEST;
The table name is received as an input parameter.
My SQL script is as follows;
spool exportTable.log
SET HEAD OFF
SET TRIMOUT ON
SET TRIMSPOOL ON
SET LINESIZE 32000
SET PAGESIZE 0
SET TERMOUT OFF
SET ECHO OFF
SET COLSEP ,
procedure CreerReq(sTable in Varchar) is
dbms_output.put_line('dans CreerReq');
sqlreq VARCHAR2(2000);
sChaine VARCHAR2(4000):='select';
TYPE t_tab IS TABLE OF VARCHAR2(4000);
l_tab t_tab;
l_tab_Id t_tab;
l_ref_cursor SYS_REFCURSOR;
dbms_output.put_line(sChaine);
begin
sqlreq := 'select column_name from all_tab_cols WHERE table_name' || sTable;
dbms_output.put_line(sqlreq);
OPEN l_ref_cursor FOR sqlreq;
LOOP
FETCH l_ref_cursor BULK COLLECT INTO l_tab_Id,l_tab limit 1000;
EXIT WHEN l_tab.COUNT=0;
FOR i IN l_tab.first .. l_tab.last LOOP
sChaine:=l_tab(i) ' || ','';
END LOOP;
CLOSE l_ref_cursor;
dbms_output.put_line(sChaine);
End CreerReq;
BEGIN
dbms_output.put_line('&1');
CreerReq(&1);
END;
/
spool off;
However this is returning me the following error:
ORA-00900: invalid SQL statement
Any help please?
CREATE or replace FUNCTION build_select (
p_owner IN VARCHAR2
, p_table_name IN VARCHAR2
)
RETURN VARCHAR2
AS
l_ret VARCHAR2 (32767);
BEGIN
FOR eachcol IN ( SELECT column_name
, LEAD (column_name)
OVER (
PARTITION BY table_name ORDER BY column_id
)
next_column
FROM all_tab_cols
WHERE owner = p_owner
AND table_name = p_table_name
ORDER BY column_id)
LOOP
l_ret := l_ret || eachcol.column_name || CASE WHEN eachcol.next_column IS NULL THEN NULL ELSE ',' END;
END LOOP;
IF l_ret IS NULL
THEN
raise_application_error (-20001, 'table ' || p_owner || '.' || p_table_name || ' not found');
END IF;
l_ret := 'select ' || l_ret || ' from ' || p_owner || '.' || p_table_name;
RETURN l_ret;
END build_select;
So let's test it out:
begin dbms_output.put_line(build_select('SYS', 'ALL_TAB_COLS')); end;
Results in:
select OWNER,TABLE_NAME,COLUMN_NAME,DATA_TYPE,DATA_TYPE_MOD,DATA_TYPE_OWNER,DATA_LENGTH,DATA_PRECISION,DATA_SCALE,NULLABLE,COLUMN_ID,DEFAULT_LENGTH,DATA_DEFAULT,NUM_DISTINCT,LOW_VALUE,HIGH_VALUE,DENSITY,NUM_NULLS,NUM_BUCKETS,LAST_ANALYZED,SAMPLE_SIZE,CHARACTER_SET_NAME,CHAR_COL_DECL_LENGTH,GLOBAL_STATS,USER_STATS,AVG_COL_LEN,CHAR_LENGTH,CHAR_USED,V80_FMT_IMAGE,DATA_UPGRADED,HIDDEN_COLUMN,VIRTUAL_COLUMN,SEGMENT_COLUMN_ID,INTERNAL_COLUMN_ID,HISTOGRAM,QUALIFIED_COL_NAME from SYS.ALL_TAB_COLS
Here is a simpler build_select function:
CREATE OR REPLACE FUNCTION build_select (
p_owner IN VARCHAR2
, p_table_name IN VARCHAR2
)
RETURN VARCHAR2
AS
l_ret VARCHAR2 (32767);
BEGIN
SELECT
LISTAGG (column_name, ',') WITHIN GROUP (ORDER BY column_id)
INTO l_ret
FROM all_tab_cols
WHERE table_name = p_table_name
AND owner = p_owner;
IF l_ret IS NULL
THEN
raise_application_error (-20001, 'table ' || p_owner || '.' || p_table_name || ' not found');
END IF;
l_ret := 'select ' || l_ret || ' from ' || p_owner || '.' || p_table_name;
RETURN l_ret;
END build_select;
I haven't worked with oracle in a while. But on sql server this is how it can be done. Look through this code and it might point you to the right direction:
/* This stored procedure builds dynamic SQL and executes
using sp_executesql */
Create Procedure sp_EmployeeSelect
/* Input Parameters */
#EmployeeName NVarchar(100),
#Department NVarchar(50),
#Designation NVarchar(50),
#StartDate DateTime,
#EndDate DateTime,
#Salary Decimal(10,2)
AS
Set NoCount ON
/* Variable Declaration */
Declare #SQLQuery AS NVarchar(4000)
Declare #ParamDefinition AS NVarchar(2000)
/* Build the Transact-SQL String with the input parameters */
Set #SQLQuery = 'Select * From tblEmployees where (1=1) '
/* check for the condition and build the WHERE clause accordingly */
If #EmployeeName Is Not Null
Set #SQLQuery = #SQLQuery + ' And (EmployeeName = #EmployeeName)'
If #Department Is Not Null
Set #SQLQuery = #SQLQuery + ' And (Department = #Department)'
If #Designation Is Not Null
Set #SQLQuery = #SQLQuery + ' And (Designation = #Designation)'
If #Salary Is Not Null
Set #SQLQuery = #SQLQuery + ' And (Salary >= #Salary)'
If (#StartDate Is Not Null) AND (#EndDate Is Not Null)
Set #SQLQuery = #SQLQuery + ' And (JoiningDate
BETWEEN #StartDate AND #EndDate)'
/* Specify Parameter Format for all input parameters included
in the stmt */
Set #ParamDefinition = ' #EmployeeName NVarchar(100),
#Department NVarchar(50),
#Designation NVarchar(50),
#StartDate DateTime,
#EndDate DateTime,
#Salary Decimal(10,2)'
/* Execute the Transact-SQL String with all parameter value's
Using sp_executesql Command */
Execute sp_Executesql #SQLQuery,
#ParamDefinition,
#EmployeeName,
#Department,
#Designation,
#StartDate,
#EndDate,
#Salary
If ##ERROR <> 0 GoTo ErrorHandler
Set NoCount OFF
Return(0)
ErrorHandler:
Return(##ERROR)
GO
Related
Please what is the effective way for getting the rows where the first column (primary index) is populated but all other columns are null? The table has 25 columns and I want to avoid putting all column names in the WHERE clause.
Thanks.
One of many methods (this will give you a generated SQL to run, but you can amend the code just to get its results through insert select, for instance)
create table test_table_2000 ( charcol1 varchar(2000) );
replace procedure sp_find_blank_rows( in_database varchar(50), in_tablename varchar(50) )
begin
declare
l_sql varchar(2000);
declare
l_int integer;
set l_sql = 'select * from '||in_database||'.'||in_tablename||' where 1=1 ';
FOR fReq AS cReq CURSOR FOR
select * from Dbc.Columns where databaseName=in_database and TableName=in_tablename order by ColumnId
DO
IF l_int is null THEN
SET l_sql = l_sql || ' and ' || fReq.ColumnName || ' is not null ';
ELSE
SET l_sql = l_sql || ' and ' || fReq.ColumnName || ' is null ';
END IF;
set l_int = 1;
END FOR;
insert into test_table_2000 values ( l_sql );
end;
call sp_find_blank_rows('<your_database>','<your_table>');
I have a simple Cursor in SQL Server that I would like to adapt to use in Teradata.
The goal of the cursor is to collect the names of a series of tables and rename them using cursor logic.
I already change most of the cursor code to use in Teradata, but I'm still having some trouble to finish this.
So far I have:
DECLARE varTableOldName VARCHAR(500);
DECLARE varTableNewName VARCHAR(500);
DECLARE vardbName VARCHAR(100);
DECLARE varIDCod VARCHAR(5);
DECLARE varRename VARCHAR(100);
DECLARE varCt INT DEFAULT 0;
DECLARE renameTables CURSOR FOR
SELECT
DBname
,TBname
FROM (
SELECT
DatabaseName AS DBname
,TableName AS TBname
,LastAccessTimeStamp AS LADate
,(CURRENT_DATE - CAST(LastAccessTimeStamp AS DATE)) AS NAccessDate
FROM
DBC.TablesV
WHERE
1=1
AND TableKind = 'T'
AND DatabaseName IN ('PD_BACKUP')
GROUP BY
DatabaseName
,TableName
,LastAccessTimeStamp
,LastAlterTimeStamp
) tbHig
WHERE NAccessDate IS NULL OR NAccessDate >= 180
ORDER BY DBname, TBname
FOR READ ONLY;
OPEN renameTables;
FETCH NEXT FROM renameTables
INTO vardbName, varTableOldName;
WHILE (SQLCODE = 0)
DO
SET varTableNewName = vardbName || '_V' || CAST(EXTRACT(YEAR FROM CURRENT_TIMESTAMP) AS VARCHAR(20)) || '_' || CAST(varCt AS VARCHAR(20));
SET varTableOldName = vardbName || '.' || varTableOldName;
SET varRename = 'RENAME TABLE ' || varTableOldName || ' TO ' || varTableNewName;
EXECUTE IMMEDIATE varRename;
SET varCt = varCt + 1;
FETCH NEXT FROM renameTables INTO vardbName, varTableOldName;
END WHILE;
CLOSE renameTables;
I think the problem is with some syntax details or something.
Can anyone guide me with this please?
The code for the function is as follows:
CREATE OR REPLACE FUNCTION FTTH_GETBUSZONECODEMULTI(
p_house_nbr IN VARCHAR2,
p_as_of_date IN DATE DEFAULT SYSDATE)
RETURN VARCHAR2
AS
CURSOR l_get_cur
IS
SELECT
LTRIM(RTRIM(BZO.B2FEDC)) BusinessZoneCode
FROM
[not wasting your time with business logic]
l_return VARCHAR2(32767);
BEGIN
--
FOR l_get_rec IN l_get_cur LOOP
l_return := l_return || '|' || l_get_rec.BusinessZoneCode;
END LOOP;
--
CASE
WHEN l_return IS NULL THEN RETURN NULL;
ELSE RETURN l_return || '|';
END CASE;
--
END FTTH_GETBUSZONECODEMULTI;
My attempt at translating it is below:
CREATE FUNCTION ftth_GETBUSZONECODEMULTI(
#p_house_nbr VARCHAR(4000),
#p_as_of_date DATETIME)
RETURNS VARCHAR(4000)
AS
BEGIN
SET #p_as_of_date = GETDATE()
DECLARE l_get_cur CURSOR LOCAL
FOR
SELECT
LTRIM(RTRIM(BZO.B2FEDC)) BusinessZoneCode
FROM
[not wasting your time with business logic]
DECLARE #l_return VARCHAR(MAX);
--
SET #l_return = isnull(#l_return, '') + '|' + ISNULL((FETCH BusinessZoneCode from l_get_cur), '');
--
if #l_return IS NULL begin RETURN NULL END
if #l_return is not null BEGIN RETURN isnull(#l_return, '') + '|' END;
END
The problem is with, I think, how I'm trying to FETCH the value - even if I put a "NEXT" in there it doesn't work right. I've tried like 6 different ways to arrange the FETCH and none of them work.
here is some changes in cursor usage, I might be wrong where you cursor loop end , so you might need to adjust it:
CREATE FUNCTION ftth_GETBUSZONECODEMULTI(
#p_house_nbr VARCHAR(4000),
#p_as_of_date DATETIME)
RETURNS VARCHAR(4000)
AS
BEGIN
declare #BusinessZoneCode varchar(500)
SET #p_as_of_date = GETDATE()
DECLARE l_get_cur CURSOR LOCAL
FOR
SELECT
LTRIM(RTRIM(BZO.B2FEDC)) BusinessZoneCode
FROM
[not wasting your time with business logic]
OPEN l_get_cur
fetch next from l_get_cur
into #BusinessZoneCode
WHILE ##FETCH_STATUS = 0
begin
DECLARE #l_return VARCHAR(MAX);
--
SET #l_return = isnull(#l_return, '') + '|' + ISNULL((#BusinessZoneCode), '');
--
if #l_return IS NULL begin RETURN NULL END
if #l_return is not null BEGIN RETURN isnull(#l_return, '') + '|' END
fetch next from l_get_cur
into #BusinessZoneCode
end
close l_get_cur
deallocate l_get_cur
END
If I have a table:
create table thisTable (
column1 varchar(20),
column2 varchar(20),
column3 varchar(20)
);
and I want to transfer data to a 1 column XML table:
create table XMLTable (
data1 sys.xmltype
);
<column2>
<column1>..</column1>
<column2>..</column2>
<column3>..</column3>
</column2>
How would I do that?
INSERT INTO XMLTABLE
SELECT
XMLELEMENT(
"column2",
XMLELEMENT("column1", COLUMN1), XMLELEMENT("column2", COLUMN2), XMLELEMENT("column3", COLUMN3)
)
FROM
thisTable;
You can insert it using below procedure.
declare
sourceTable varchar2(80) := 'THISTABLE';
destTable varchar2(80) := 'XMLTABLE';
destColumn varchar2(80) := 'data1';
TYPE cur_typ IS REF CURSOR;
c cur_typ;
colu varchar2(2000);
vsql varchar2(2000) := ' select ';
begin
for r in (select column_name from user_tab_columns where table_name = sourceTable order by column_id)
loop
vsql := vsql || ''' <' || r.column_name || '>'' || ' || r.column_name || ' || ''</' || r.column_name || '> '' || ' ;
end loop;
vsql := substr(vsql, 0 ,length(vsql)-4);
vsql := vsql ||' as x From ' || sourceTable;
open c for vsql ;
loop
FETCH c INTo colu;
EXIT WHEN c%NOTFOUND;
dbms_output.put_line(colu);
execute immediate ' insert into ' || destTable || ' values (xmltype(''<column2>' || colu || '</column2>'')) ';
end loop;
close c;
end;
I am dynamcially naming temporary table, inserting some data to this dynamic-named temporary table.
But I am not able to get back the data from dynamic-named temporary table to function variable to do my calculation.
How can I execute 'select into ....' inside plpgsql function from/with dynamic-named temporary table?
drop table dummy;
drop table mytable;
create table dummy (id bigint,parent_id bigint);
insert into dummy values(600,null);
insert into dummy values(12,600);
insert into dummy values(700,null);
DROP FUNCTION total_test(bigint,text,text,date,bigint[],text);
CREATE OR REPLACE FUNCTION total_test(bigint,text,text,date,dep bigint[],tname text) RETURNS double precision AS '
DECLARE pid BIGINT;
DECLARE total DOUBLE PRECISION;
DECLARE array_len int;
DECLARE myDepIds bigint[];
BEGIN
IF dep IS NOT NULL THEN
total :=0;
array_len := array_upper(DEP, 1);
EXECUTE ''CREATE TEMPORARY TABLE '' || tname || '' (dep_id bigint )'';
FOR i IN 1 .. array_len
LOOP
EXECUTE ''INSERT INTO '' || tname || '' values (''|| DEP[i] ||'')'';
select into pid id from dummy where parent_id in (DEP[i]);
IF pid IS NOT NULL THEN
EXECUTE ''INSERT INTO '' || tname || '' values (''|| pid || '')'';
END IF;
END LOOP;
--works where tname:=''mytable''; select into myDepIds array(select distinct(dep_id) from mytable where dep_id is not null);
--not working; EXECUTE ''select into myDepIds array(select distinct(dep_id) from '' || $7 || '' where dep_id is not null)'';
--not working; EXECUTE ''select into myDepIds array(select distinct(dep_id) from '' || tname || '' where dep_id is not null)'';
EXECUTE ''select into '' || myDepIds || '' array(select distinct(dep_id) from '' || tname || '' where dep_id is not null)'';
--not working; EXECUTE ''select into cast(myDepIds as bigint[]) array(select distinct(dep_id) from '' || tname || '' where dep_id is not null)'';
--calculation....
--EXECUTE ''DROP TABLE '' || tname;
RETURN total;
END IF;
END;
' LANGUAGE plpgsql;
select total_test(11269, 'sales', 'A', date('06/02/2011'), ARRAY[600], 'mytable') as value;
select * from mytable;
Should be:
EXECUTE sql_string INTO var