I'm a bit stuck. I have a table with a list of database names. I want to query for the database name and then query this database to return details from its "systemtable".
I've been trying to use 2 cursors but its not quite working out for me (just can't find the syntax), any pointers/help would be appreciated.
declare
cursor c_dbNames is select dbname
from DB_INFO order by name ASC;
v_curr_dbname VARCHAR2(60);
begin
open c_dbNames;
LOOP
FETCH c_dbNames into v_curr_dbname;
EXIT WHEN c_dbnames%NOTFOUND;
begin
cursor c_dbDetails is select value
from SYSTEMTABLE#'||v_curr_dbname||' order by name ASC;
v_curr_detail VARCHAR2(60);
open c_dbDetails;
LOOP
FETCH c_dbDetails into v_curr_detail;
EXIT WHEN c_dbDetails%NOTFOUND;
htp.p('<tr><th>'||v_curr_detail||'</th></tr>');
END LOOP;
close c_dbDetails;
end;
END LOOP;
close c_dbnames;
end;
You have to adjust it a little:
declare
cursor c_dbNames is
select 'dual' dbname from dual union all
select 'dual' dbname from dual union all
select 'dual' dbname from dual
order by dbname ASC;
v_curr_dbname VARCHAR2(60);
begin
open c_dbNames;
LOOP
FETCH c_dbNames into v_curr_dbname;
EXIT WHEN c_dbnames%NOTFOUND;
DECLARE
v_cursor integer;
v_rows integer;
v_curr_detail char(20);
begin
v_cursor := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(v_cursor, 'select ''c_dbDetails'' c_dbDetails FROM ' || v_curr_dbname, DBMS_SQL.NATIVE);
DBMS_SQL.DEFINE_COLUMN_CHAR(v_cursor, 1, v_curr_detail, 20);
v_rows := DBMS_SQL.EXECUTE(v_cursor);
loop
if DBMS_SQL.FETCH_ROWS(v_cursor) = 0 then
exit;
end if;
DBMS_SQL.COLUMN_VALUE_CHAR(v_cursor, 1, v_curr_detail);
DBMS_OUTPUT.PUT_LINE('<tr><th>' || v_curr_detail ||'</th></tr>');
end loop;
DBMS_SQL.CLOSE_CURSOR(v_cursor);
end;
END LOOP;
close c_dbnames;
end;
declare
cursor databases_c is
-- put your database links here
select 'XXX' as dbname from dual union
select 'YYY' from dual;
v_global_name varchar2(4000);
begin
for v_dbname in databases_c loop
-- query the database details
execute immediate
'select global_name from global_name#' || v_dbname.dbname
into v_global_name;
dbms_output.put_line(v_global_name);
end loop;
end;
/
Output:
SQL> #so27.sql
XXX
YYY
PL/SQL procedure successfully completed.
SQL>
Related
I am have created a stored procedure in oracle. Now I need to convert the same procedure to SQL Server procedure. Since I am not good at SQL procedure, please help me.
Following is the Oracle Procedure:
create or replace
PROCEDURE "FTSREMOVESPECIALCHAR"
AS strquery VARCHAR2(4000 byte);
stmt VARCHAR2(1000);
l_cursor SYS_REFCURSOR;
TYPE result_rec IS RECORD (iid NUMBER(10, 0),
fulltextdetails VARCHAR2(4000 byte),
regex VARCHAR2(4000 byte));
l_result_rec RESULT_REC;
idValue NUMBER(10, 0);
fulltextdetailsValue VARCHAR2(4000 byte);
fulltextWithoutSplChr VARCHAR2(4000 byte);
regexValue VARCHAR2(4000 byte);
minmatchValue NUMBER(10, 0);
strQueryinsert VARCHAR2(4000 byte);
BEGIN
dbms_output.ENABLE(1000000);
FOR c IN (SELECT table_name
FROM user_tables
WHERE table_name LIKE 'FULLTEXTLOOKTABLE_%')
LOOP
dbms_output.Put_line(c.table_name);
strquery := 'select ID, FullTextDetails, Regex from ' || c.table_name;
BEGIN
OPEN l_cursor FOR strquery;
LOOP
FETCH l_cursor INTO l_result_rec;
Exit when l_cursor%NOTFOUND;
fulltextdetailsValue := l_result_rec.fulltextdetails;
regexValue := l_result_rec.regex;
dbms_output.Put_line('Before :' ||fulltextdetailsValue);
fulltextdetailsValue := regexp_replace(fulltextdetailsValue, '[^[:alnum:] ]', NULL);
dbms_output.Put_line('After : '||fulltextdetailsValue);
dbms_output.Put_line('Before regexValue:' ||regexValue);
regexValue := replace(regexValue, '([\~\-])', '([\~\-])?');
regexValue := replace(regexValue, '(\!)', '(\!)?');
regexValue := replace(regexValue, '([\#])', '([\#])?');
regexValue := replace(regexValue, '(\#)', '(\#)?');
regexValue := replace(regexValue, '([\$s\&])', '([\$s\&])?');
regexValue := replace(regexValue, '(\%)', '(\%)?');
regexValue := replace(regexValue, '(\^)', '(\^)?');
regexValue := replace(regexValue, Q'[']',Q'['']');
strQueryinsert := 'update '||c.table_name||' set fulltextdetails='''||fulltextdetailsValue||''' where id='||l_result_rec.iid;
dbms_output.Put_line('strQueryinsert : ' ||strQueryinsert);
EXECUTE IMMEDIATE
strQueryinsert;
strQueryinsert := 'update '||c.table_name||' set regex='''||regexValue||''' where id='||l_result_rec.iid;
EXECUTE IMMEDIATE
strQueryinsert;
END LOOP;
EXECUTE IMMEDIATE
'commit';
close l_cursor;
END;
END LOOP;
END;
This procedure will get the all tables from the DB that starts with "FULLTEXTLOOKTABLE_". The table has 4 columns(ID(int), FullTextDetails(nvarchar), Regex(nvarchar), MinMatchCount(int)). For each table it will take the value of "FullTextDetails" column and remove all the special characters and also take the
"Regex" and replace
([\~\-]) with ([\~\-])?
(\!) with (\!)?
([\#]) with ([\#])?
(\#) with (\#)?
([\$s\&]) with ([\$s\&])?
(\%) with (\%)?
(\^) with (\^)?
And update the columns "FullTextDetails" and "Regex" with the new values. Finally the changes are committed.
The most difficult thing here is how to handle the regex replacement as in T-SQL there is not such build in function. Fortunately, you can implement such as I am showing here using SQL CLR integration - basically, you are allowed to write .net objects, to mapped them to SQL objects and use them. You need to do some effort but that's your only chance.
Then, the other things are pretty easy. From this system object you can get and loop through the table names:
SELECT *
FROM [sys].[tables];
You can use cursor but I prefer to skip them. It will be something like this:
DECLARE #Tables TABLE
(
[name] SYSNAME
);
DECLARE #CurrentTableName SYSNAME;
INSERT INTO #Tables ([name])
SELECT [name]
FROM [sys].[tables]
--WHERE [name] LIKE 'FULLTEXTLOOKTABLE_%';
WHILE EXISTS(SELECT 1 FROM #Tables)
BEGIN;
SELECT TOP 1 #CurrentTableName = [name]
FROM #Tables;
SELECT #CurrentTableName;
DELETE FROM #Tables
WHERE [name] = #CurrentTableName;
END;
For the building and executing of the dynamic T-SQL statement you have two options. You can build the whole statement and execute it for each loop like this:
DECLARE #DynamicTSQLStatement NVARCHAR(MAX);
SET #DynamicTSQLStatement = N'UPDATE [dbo].[table] SET [text] = ''test'' WHERE [ID] = 1';
EXEC sp_executesql #DynamicTSQLStatement;
or you can use the sp_executesql with parameters and create a template which is populated with the current values.
I hope this points will be enough to handle the task.
I have a one time-monthly JOB with 3 steps, each runs a different SP, how can I get the 1st SP only to start running when I have all the information required ?
ie: I require Table A and Table B information to run SP1 before it goes to step 2 and 3 of the JOB, how do I tell that to the program?
before the execute statement add a check for Table A and Table B. Like this
IF EXISTS(SELECT 1 FROM tableA) AND EXISTS(SELECT 1 FROM TableB)
BEGIN
EXEC YourProcedure
END
If you want to run the Execute only if both tables exist in the database try this
DECLARE #Cnt INT = 0
SELECT #Cnt COUNT(1) FROM sys.objects WHERE Object_Id = OBJECT_ID('tableA')OR Object_Id = OBJECT_ID('tableB')
IF ISNULL(#Cnt,0)=2
BEGIN
EXEC YourProcedure
END
or If you want to loop it till the tables are created, then try this
DECLARE #Cnt INT = 0
WHILE ISNULL(#Cnt,0) <2
BEGIN
SELECT #Cnt COUNT(1) FROM sys.objects WHERE Object_Id = OBJECT_ID('tableA')OR Object_Id = OBJECT_ID('tableB')
IF ISNULL(#Cnt,0)=2
BEGIN
EXEC YourProcedure
END
END
If you want to run the Procedure at a specific time. Then Probably you can schedule it for that particular time in the SQL Job or SSIS Package. Or If you want to do that check in the SQL Script (Not Recommended) Then try this
WHILE(1)
BEGIN
IF(SELECT 1 WHERE GETDATE() = 'dd/mm/yyy hh:ss:mm')
BEGIN
EXEC YourProcedure
END
END
Getting error while using two cursors
[Error] PLS-00103 (45: 48): PLS-00103: Encountered the symbol
"TX_COM_LOCATION" when expecting one of the following:
:= . ( # % ;
The symbol ":=" was substituted for
"TX_COM_LOCATION" to continue.
Please help
CREATE OR REPLACE PROCEDURE COM_LOCATION_TXM
IS
BEGIN
DECLARE CURSOR TXM_COM_LOCATION IS SELECT col1,col2,col3 from TBL_SAR_SALAS_1 A;
CURSOR TX_COM_LOCATION is select col1,col2,col3 from TBL_LOCALES B;
TMP_TXM TXM_COM_LOCATION%ROWTYPE;
TMP_TXM TX_COM_COCATION%ROWTYPE;
Begin
IF NOT TXM_COM_LOCATION%ISOPEN
THEN OPEN TXM_COM_LOCATION;
END IF;
FETCH TXM_COM_LOCATION INTO TMP_TXM;
EXIT
WHEN TXM_COM_LOCATION%NOTFOUND;
IF NOT TX_COM_LOCATION%ISOPEN
THEN
OPEN TXCOM_LOCATION;
END IF;
LOOP FETCH TX_COM_LOCATION INTO TMP_TX; EXIT WHEN TX_COM_LOCATION%NOTFOUND;
BEGIN Insert statement()
END;
END LOOP;
END LOOP;
commit;
END;
END COM_LOCATION_TXM ;
Check this:
CREATE OR REPLACE PROCEDURE COM_LOCATION_TXM IS BEGIN DECLARE CURSOR TXM_COM_LOCATION IS SELECT col1, col2, col3 FROM TBL_SAR_SALAS_1 A; CURSOR TX_COM_LOCATION IS SELECT col1, col2, col3 FROM TBL_LOCALES B; TMP_TXM TXM_COM_LOCATION%ROWTYPE; TMP_TXM TX_COM_LOCATION%ROWTYPE; BEGIN IF NOT TXM_COM_LOCATION%ISOPEN THEN OPEN TXM_COM_LOCATION; END IF; LOOP FETCH TXM_COM_LOCATION INTO TMP_TXM; EXIT WHEN TXM_COM_LOCATION%NOTFOUND; IF NOT TX_COM_LOCATION%ISOPEN THEN OPEN TXCOM_LOCATION; END IF; LOOP FETCH TX_COM_LOCATION INTO TMP_TX; EXIT WHEN TX_COM_LOCATION%NOTFOUND; BEGIN NULL; -- REPLACE NULL WITH INSERT STATEMENT END; END LOOP; END LOOP; COMMIT; END; END COM_LOCATION_TXM;
Can we have a Procedure with
First create a table suppose
create table INCOME_GROUP(income_compare_groups varchar(100)) ;
Then insert data into this table.
insert into INCOME_GROUP values (10-20);
Then Use this table into a cursor.
CURSOR c1 IS(select *from INCOME_GROUP);
For Example I am doing this.
BEGIN
create table INCOME_GROUP(income_compare_groups varchar(100)) ;
DECLARE
CURSOR c1 IS(select * income_Group);
BEGIN
FOR acct IN c1 LOOP -- process each row one at a time
INSERT INTO temp_test
VALUES (acct.income_compare_groups);
END LOOP;
COMMIT;
END;
END;
But I am getting some Error.
ORA-06550: line 2, column 4:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
( begin case declare exit for goto if loop mod null pragma
raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
continue close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe purge
After reading the comments I tried this -
BEGIN
EXECUTE IMMEDIATE 'create table INCOME_GROUP
(
income_compare_groups varchar(100)
)';
DECLARE
CURSOR c1 IS
(select * from
INCOME_GROUP
);
BEGIN
FOR acct IN c1 LOOP -- process each row one at a time
INSERT INTO temp_test
VALUES (acct.income_compare_groups, null);
END LOOP;
COMMIT;
END;
END;
But seems it is not creating table.!!!!
You can do it like this:
create or replace procedure cpy_inc_comp_grps
as
cur_1 sys_refcursor;
compare_group varchar2(100);
begin
execute immediate 'create table income_group(income_compare_groups varchar2(100))';
open cur_1 for 'select income_compare_groups from income_group';
LOOP
FETCH cur_1 INTO compare_group;
DBMS_OUTPUT.PUT_LINE('INSERT INTO temp_test VALUES (rec.income_compare_groups');
EXIT WHEN cur_1%NOTFOUND;
END LOOP;
close cur_1;
execute immediate 'drop table income_group';
end;
And test it with the following code:
begin
cpy_inc_comp_grps;
end;
You have to replace the dbms_output.put_line(...) part with whatever inserts you want to do.
It must be like this:
DECLARE
cur SYS_REFCURSOR;
v_income_compare_groups VARCHAR(100);
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE INCOME_GROUP(income_compare_groups VARCHAR(100))';
OPEN cur FOR 'SELECT * income_Group';
LOOP
FETCH cur INTO v_income_compare_groups;
EXIT WHEN cur%NOTFOUND;
INSERT INTO temp_test VALUES (v_income_compare_groups);
END LOOP;
CLOSE cur;
COMMIT;
END;
You have to use dynamic Cursor because when you compile the package then the table INCOME_GROUP does not exist yet and you would get an error at CURSOR c1 IS(select * income_Group);
However, there are several issue:
You will get an error if the table already exist. You have to check this first or write an exception handler.
The procedure is useless because you first create an (empty) table and then you select it - it will never select anything!
Try this.
execute immediate 'create table INCOME_GROUP(income_compare_groups varchar(100))';
Hi I have been trying this today and haven't had any luck. this stored procedure does not work :(
CREATE OR REPLACE PROCEDURE LEAD_PURGE(closed IN DATE,
oprtr IN INTEGER,
leadscount OUT INTEGER)
is
BEGIN
SELECT COUNT(*) FROM LEADS_DELETED INTO leadscount;
COMMIT;
END LEAD_PURGE;
The INTO clause is misplaced. It should be:
SELECT COUNT(*) INTO leadscount FROM LEADS_DELETED
you have the into at the wrong place.
Try something like this instead and proceed from there:
declare
cnt number;
begin
select count(*)
into cnt
from leads_delete;
end;
Another way :
declare
cnt number;
cmd varchar2(100);
begin
cmd := 'select count(*) from leads_delete';
execute immediate cmd into cnt;
end;