I have an oracle database and I am running the below query
select table_name
from db_test.test
where table_name like '%20170128'
This returns me a column with all the tables with the specific date at the end.
How can I take this list and query them?
You'd need dynamic SQL. If you're running a simple query against each table (I'm just doing a count(*) in this example), something like this would work
declare
l_cnt integer;
l_sql varchar2(1000);
begin
for t in (select table_name
from db_test.test
where table_name like '%20170128')
loop
l_sql := 'select count(*) from ' || t.table_name;
execute immediate l_sql
into l_cnt;
dbms_output.put_line( t.table_name || ' has ' || l_cnt || ' rows.' );
end loop;
end;
When I execute the following code I get , sql command not ended properly.
I'm using this to find matching column for a string.
DECLARE
match_count INTEGER;
BEGIN
FOR t IN (SELECT table_name, column_name FROM all_tab_cols where owner=v_owner and data_type = v_data_type) LOOP
EXECUTE IMMEDIATE
'SELECT COUNT(*) FROM '||t.table_name||' WHERE lower('||t.column_name||') like :1'
INTO match_count
USING 'XRWJ01';
IF match_count > 0 THEN
dbms_output.put_line( t.table_name ||' '||t.column_name||' '||match_count );
END IF;
END LOOP;
END;
/
Debug your code... if you get an error print the statement erroring out. I made some minor changes to your pl/sql block. Replace v_owner and v_datatype with your values to run it.
set serveroutput on size 999999
clear screen
DECLARE
match_count INTEGER;
v_owner VARCHAR2(30);
v_data_type VARCHAR2(30);
v_stmt VARCHAR2(1024);
BEGIN
v_owner := 'SCOTT';
v_data_type := 'NUMBER';
FOR t IN (SELECT table_name, column_name FROM all_tab_cols where owner=v_owner and data_type = v_data_type) LOOP
v_stmt := 'SELECT COUNT(*) FROM "'||t.table_name||'" WHERE "'||t.column_name||'" like :1';
BEGIN
EXECUTE IMMEDIATE
v_stmt
INTO match_count
USING 'XRWJ01';
EXCEPTION WHEN OTHERS THEN
dbms_output.put_line( 'Error in statement: '|| v_stmt );
dbms_output.put_line ( DBMS_UTILITY.FORMAT_ERROR_STACK() );
dbms_output.put_line ( DBMS_UTILITY.FORMAT_ERROR_BACKTRACE() );
END;
IF match_count > 0 THEN
dbms_output.put_line( t.table_name ||' '||t.column_name||' '||match_count );
END IF;
END LOOP;
END;
/
I ran the statement locally and it errored out because of LOWER('||t.column_name||'). You select the columns from a data dictionary - those are the column names. If you do a LOWER then you might have different values if the tables/columns are created with case. Solution is to not do LOWER and put double quotes around them.
I'm trying to code a statement that checks if a table exist and if it does to truncate/delete it. If it doesn't exist, to print the message 'This table does not exist!'
This is what I've come up so far but doesn't seem to work.
BEGIN
TRUNCATE TABLE PPA_P6_2018;
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_OUTPUT.put_line('This table does not exist!');
ELSE
RAISE;
DBMS_OUTPUT.put_line('This table has been delted!');
END IF;
END;
Create a custom exception to catch when the table does not exist and then only catch that single exception (rather than catching all of them with OTHERS) and then use EXECUTE IMMEDIATE to truncate/drop the table:
DECLARE
table_name VARCHAR2(30) := 'PPA_P6_2018';
table_not_exists EXCEPTION;
PRAGMA EXCEPTION_INIT( table_not_exists, -942 );
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || table_name;
EXECUTE IMMEDIATE 'DROP TABLE ' || table_name;
DBMS_OUTPUT.put_line('This table has been deleted!');
EXCEPTION
WHEN table_not_exists THEN
DBMS_OUTPUT.put_line('This table does not exist!');
END;
/
db<>fiddle
TRUNCATE TABLE is DDL so cannot be run directly within PL/SQL. You need to use EXECUTE IMMEDIATE:
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE PPA_P6_2018';
EXCEPTION
WHEN OTHERS THEN
IF SQLCODE = -942 THEN
DBMS_OUTPUT.put_line('This table does not exist!');
ELSE
RAISE;
DBMS_OUTPUT.put_line('This table has been delted!');
END IF;
END;
Note: You will never see the message 'This table has been delted!' since the RAISE before it throws you out of the block! And if you got an error, the table hasn't been deleted anyway!
DECLARE
v_count NUMBER;
v_table_name VARCHAR2 (100) := 'YOURTABLE';
v_sqlstr VARCHAR2 (1000);
BEGIN
SELECT COUNT ( * )
INTO v_count
FROM user_tables
WHERE table_name = v_table_name;
IF v_count > 0
THEN
v_sqlstr := 'DELETE FROM ' || v_table_name;
EXECUTE IMMEDIATE v_sqlstr;
DBMS_OUTPUT.put_line (
'TABLE ' || v_table_name || ' HAS BEEN DELETED!');
ELSE
DBMS_OUTPUT.put_line ('TABLE ' || v_table_name || ' DOES NOT EXIST!');
END IF;
END;
I have created a lookup table which holds Insert statements. Some of the values in the values have apostrophes in them.
The value appears like this
'SCRW, PAN-HD PHIL, THR'D: 8-32. L: 3/8""'
Whole statement is:
INSERT INTO PARTS_BOMD (BOM_ID, ITEM_REV, ITEM_CN, ITEM_NUMBER, ITEMNUMBER, FINDNUM, QTY, ITEMDESCRIPTION, ITEMREV, ITEMSIZE, REFDES, BOMTEXT02, ITEMLIST21, SUMMARYCOMPLIANCE, BOMMULTITEXT30, BOMNOTES, ITEMLIST10, BOMLIST01, BOMLIST03, BOMLIST02, ITEMTEXT22, ITEMTEXT23, ITEMLIFECYCLEPHASE, ITEMP2MULTILIST05, ITEMTEXT15, RNUM) VALUES (2009034062,'31','ECO05447','1472096','1422042','100','4','SCRW, PAN-HD PHIL, THR'D: 8-32. L: 3/8""','A0 MPL03682','PC','PC','','6 out of 6 Compliant','Missing Info','Missing Info','','ZHLB','','','X','','','AREL','Yes','0.10220',582272);
This table have more than 4 million records and this issue occurs most of the time.
Is there any way I can change this apostrophe into two single quotes.
I am using SQL Server 2014.
Oracle scripts which generates these insert statements:
set serveroutput on size 100000
set feedback off
declare
v_table_name varchar2(30) := 'PARTS_BOMD'; -- Your Tablename
v_column_list varchar2(2000);
v_insert_list varchar2(2000);
v_ref_cur_columns varchar2(4000);
v_ref_cur_query varchar2(2000);
v_ref_cur_output varchar2(2000);
v_column_name varchar2(2000);
cursor c1 is select column_name, data_type from user_tab_columns where table_name = v_table_name order by column_id;
refcur sys_refcursor;
begin
for i in c1 loop
v_column_list := v_column_list||','||i.column_name;
if i.data_type = 'NUMBER' then
v_column_name := i.column_name;
elsif i.data_type = 'DATE' then
v_column_name := chr(39)||'to_date('||chr(39)||'||chr(39)'||'||to_char('||i.column_name||','||chr(39)||'dd/mm/yyyy hh:mi:ss'||chr(39)||')||chr(39)||'||chr(39)||', '||chr(39)||'||chr(39)||'||chr(39)||'dd/mm/rrrr hh:mi:ss'||chr(39)||'||chr(39)||'||chr(39)||')'||chr(39);
elsif i.data_type = 'VARCHAR2' then
v_column_name := 'chr(39)||'||i.column_name||'||chr(39)';
end if;
v_ref_cur_columns := v_ref_cur_columns||'||'||chr(39)||','||chr(39)||'||'||v_column_name;
end loop;
v_column_list := ltrim(v_column_list,',');
v_ref_cur_columns := substr(v_ref_cur_columns,8);
v_insert_list := 'INSERT INTO '||v_table_name||' ('||v_column_list||') VALUES ';
v_ref_cur_query := 'SELECT '||v_ref_cur_columns||' FROM '||v_table_name;
open refcur for v_ref_cur_query;
loop
fetch refcur into v_ref_cur_output;
exit when refcur%notfound;
v_ref_cur_output := '('||v_ref_cur_output||');';
v_ref_cur_output := replace(v_ref_cur_output,',,',',null,');
v_ref_cur_output := replace(v_ref_cur_output,'(,','(null,');
v_ref_cur_output := replace(v_ref_cur_output,',,)',',null)');
v_ref_cur_output := replace(v_ref_cur_output,'null,)','null,null)');
v_ref_cur_output := v_insert_list||v_ref_cur_output;
--dbms_output.put_line (v_ref_cur_output);
INSERT INTO BOM_INS_LOOKUP(LOOKUP_STATMENT)
VALUES (v_ref_cur_output);
COMMIT;
end loop;
end;
/
It ain't much but it does the job.
There really isn't an easy way to approach this problem generically. How would you go about processing a list of values like this one?: 'A',',','B' Is it one or two or three values? And there are two ways to split it into two values.
Here's an approach you might take by making some assumptions about the format.
declare #pos int;
declare #s varchar(1024);
declare myCursor for select <COLUMN> from T;
open myCursor;
while ##fetch_status = 0
begin
fetch next from myCursor into #s;
set #pos = charindex(#s, '''', #pos);
while #pos > 0
begin
/* if apostrophe is followed by comma plus apostrophe
then assume this is the delimiter */
if substring(#s +',''', #pos + 1, 2) <> ','''
set #s = stuff(#s, #pos, 1, '''''');
else
set #pos = #pos + 2;
set #pos = charindex(#s, '''', #pos);
end
update T set <COLUMN> = #s where current of myCursor;
end
close myCursor;
deallocate myCursor;
It would be better to avoid the problem in the first place by properly quoting the values as the INSERT queries are generated. There are many ways to export data from Oracle that can be readily picked up by SQL Server.
I'm confused, because I don't know how to use variable as string in execute immediate clause.
declare
variable1 varchar2(30):
cur sys_refcursor;
begin
open cur for
select tablename from table1;
loop
fetch cur into variable1;
exit when cur %notfound;
execute immediate 'select count(*)
into variable1
from user_tables
where table_name =''' || variable1 || '''';
end loop;
close cur;
end;
Here variable1 is a table name. There should be a string value. How to do that? Still got an error.
The execute immediate statement should look like this:
execute immediate 'select count(*) from user_tables where table_name ='''||variable1||'''' into variable1;
with the into xxx after the query.