i am in the middle of studys and currently doing some exercises.
I am trying to make procedure that shows how many duplicats are in a row.
CREATE OR REPLACE PROCEDURE anzahl1(
tabelle VARCHAR2,
reihe VARCHAR2,
wieviel OUT NUMBER
)AS
test VARCHAR2(4000);
BEGIN
EXECUTE IMMEDIATE 'SELECT
reihe,
(COUNT(*)-1) AS Anzahl
INTO
wieviel
FROM
tabelle
GROUP BY
reihe
HAVING COUNT(*) > 1' using out wieviel;
DBMS_OUTPUT.PUT_LINE(wieviel);
END;
/
i tried many things but nothing worked...
even the result i was given by a teacher of my old school didnt work:
CREATE OR REPLACE PROCEDURE check_doppelte_Werte_p (
p_tabellenname IN USER_TAB_COLUMNS.TABLE_NAME%TYPE,
p_spaltenname IN USER_TAB_COLUMNS.COLUMN_NAME%TYPE,
p_ergebnis BOOLEAN
) OUT
IS
v_dummy NUMBER := 1;
v_sql_anweisung varchar2 (4000);
BEGIN
v_sql_anweisung :=
'SELECT MAX(COUNT ('
|| p_spaltenname
|| ')) '
|| ' FROM '
|| p_tabellenname
|| ' GROUP BY '
|| p_spaltenname;
DBMS_OUTPUT.PUT_LINE (v_sql_anweisung);
EXECUTE IMMEDIATE v_sql_anweisung INTO v_dummy;
IF v_dummy > 1 THEN
DBMS_OUTPUT.PUT_LINE( 'Die Tabelle '
|| 'hat mindestens '
|| TO_CHAR (V_DUMMY)
|| ' doppelte Werte in der Spalte '
|| p_spaltenname);
p_ergebnis := TRUE;
ELSE
p_ergebnis := FALSE;
END IF;
EXCEPTION
-- Keine Werte gefunden, da
WHEN NO_DATA_FOUND
THEN
p_ergebnis := FALSE;
DBMS_OUTPUT.PUT_LINE ('Tabellenname oder Spaltenname sind nicht vorhan-
den!!!');
END;
What would you do/change?
Your code doesn't substitute the variables in the dynamic sql.The query String has been to be appended with the input variables.
Please try the code below,
CREATE OR REPLACE PROCEDURE anzahl1(
tabelle VARCHAR2,
reihe VARCHAR2,
wieviel OUT NUMBER
)AS
test VARCHAR2(4000);
lv_query VARCHAR2(4000);
BEGIN
lv_query := 'SELECT (COUNT(*)-1) cnt FROM '||tabelle ||' GROUP BY '||reihe||' HAVING COUNT(*) > 1';
EXECUTE IMMEDIATE lv_query into wieviel;
DBMS_OUTPUT.PUT_LINE(wieviel);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('ERROR '||SQLCODE||' '||SUBSTR(SQLERRM,1,200));
END;
/
I create table and populate records as below,
CREATE TABLE EMP(ID NUMBER(10),NAME VARCHAR2(40));
INSERT INTO EMP VALUES (1, 'TEST');
INSERT INTO EMP VALUES (1, 'TEST');
INSERT INTO EMP VALUES (2, 'TEST2');
Now i call the stored procedure to test for EMP table for ID column,
declare
lv_cnt number(10);
begin
anzahl1('EMP','ID',lv_cnt);
dbms_output.put_line(lv_cnt);
end;
This give output as ,
1
Related
I am trying hard dynamic PL/SQL thing here.
I don't manage to fetch a column dynamic Query.
I am iterating on the name of the column to concatenate a full query in order to be executed on another table.
sql_req := 'select ';
for c in (SELECT name_col from TAB_LISTCOL)
loop
sql_req := sql_req || 'sum(' || c.name_col || '),';
end loop;
sql_req := sql_req || ' from ANOTHER_TAB ';
And when i try to execute it with EXECUTE IMMEDIATE or cursors or INTO/BULK COLLECT thing or just to fetch, i don't manage to iterate on the result.
I tried a lot.
Can you help me plz ? Or maybe it is not possible ?
ps : i know the coma is wrong but my code is more complexe than this : i didn't want to put more things
If you only want to get string columns, you can use listagg
select listagg(name_col, ',') WITHIN GROUP (ORDER BY null) from TAB_LISTCOL
Please see if this helps
In the absence of actual table structure and requirement, I'm creating dummy tables and query to illustrate an example:
SQL> create table another_tab
as
select 10 dummy_value1, 100 dummy_value2, 1000 dummy_value3 from dual union all
select 11 dummy_value1, 101 dummy_value2, 1001 dummy_value3 from dual union all
select 12 dummy_value1, 102 dummy_value2, 1003 dummy_value3 from dual
;
Table created.
SQL> create table tab_listcol
as select column_name from dba_tab_cols where table_name = 'ANOTHER_TAB'
;
Table created.
To reduce complexity in the final block, I'm defining a function to generate the dynamic sql query. This is based on your example and will need changes according to your actual requirement.
SQL> create or replace function gen_col_based_query
return varchar2
as
l_query varchar2(4000);
begin
l_query := 'select ';
for cols in ( select column_name cname from tab_listcol )
loop
l_query := l_query || 'sum(' || cols.cname || '), ' ;
end loop;
l_query := rtrim(l_query,', ') || ' from another_tab';
return l_query;
end;
/
Function created.
Sample output from the function will be as follows
SQL> select gen_col_based_query as query from dual;
QUERY
--------------------------------------------------------------------------------
select sum(DUMMY_VALUE1), sum(DUMMY_VALUE2), sum(DUMMY_VALUE3) from another_tab
Below is a sample block for executing a dynamic cursor using DBMS_SQL. For your ease of understanding, I've added comments wherever possible. More info here.
SQL> set serveroutput on size unlimited
SQL> declare
sql_stmt clob;
src_cur sys_refcursor;
curid number;
desctab dbms_sql.desc_tab; -- collection type
colcnt number;
namevar varchar2 (50);
numvar number;
datevar date;
l_header varchar2 (4000);
l_out_rows varchar2 (4000);
begin
/* Generate dynamic sql from the function defined earlier */
select gen_col_based_query into sql_stmt from dual;
/* Open cursor variable for this dynamic sql */
open src_cur for sql_stmt;
/* To fetch the data, however, you cannot use the cursor variable, since the number of elements fetched is unknown at complile time.
Therefore you use DBMS_SQL.TO_CURSOR_NUMBER to convert a REF CURSOR variable to a SQL cursor number which you can then pass to DBMS_SQL subprograms
*/
curid := dbms_sql.to_cursor_number (src_cur);
/* Use DBMS_SQL.DESCRIBE_COLUMNS to describe columns of your dynamic cursor, returning information about each column in an associative array of records viz., desctab. The no. of columns is returned in colcnt variable.
*/
dbms_sql.describe_columns (curid, colcnt, desctab);
/* Define columns at runtime based on the data type (number, date or varchar2 - you may add to the list)
*/
for indx in 1 .. colcnt
loop
if desctab (indx).col_type = 2 -- number data type
then
dbms_sql.define_column (curid, indx, numvar);
elsif desctab (indx).col_type = 12 -- date data type
then
dbms_sql.define_column (curid, indx, datevar);
else -- assuming string
dbms_sql.define_column (curid, indx, namevar, 100);
end if;
end loop;
/* Print header row */
for i in 1 .. desctab.count loop
l_header := l_header || ' | ' || rpad(desctab(i).col_name,20);
end loop;
l_header := l_header || ' | ' ;
dbms_output.put_line(l_header);
/* Loop to retrieve each row of data identified by the dynamic cursor and print output rows
*/
while dbms_sql.fetch_rows (curid) > 0
loop
for indx in 1 .. colcnt
loop
if (desctab (indx).col_type = 2) -- number data type
then
dbms_sql.column_value (curid, indx, numvar);
l_out_rows := l_out_rows || ' | ' || rpad(numvar,20);
elsif (desctab (indx).col_type = 12) -- date data type
then
dbms_sql.column_value (curid, indx, datevar);
l_out_rows := l_out_rows || ' | ' || rpad(datevar,20);
elsif (desctab (indx).col_type = 1) -- varchar2 data type
then
dbms_sql.column_value (curid, indx, namevar);
l_out_rows := l_out_rows || ' | ' || rpad(namevar,20);
end if;
end loop;
l_out_rows := l_out_rows || ' | ' ;
dbms_output.put_line(l_out_rows);
end loop;
dbms_sql.close_cursor (curid);
end;
/
PL/SQL procedure successfully completed.
Output
| SUM(DUMMY_VALUE1) | SUM(DUMMY_VALUE2) | SUM(DUMMY_VALUE3) |
| 33 | 303 | 3004 |
You have to use EXECUTE IMMEDIATE with BULK COLLECT
Below is an example of the same. For more information refer this link
DECLARE
TYPE name_salary_rt IS RECORD (
name VARCHAR2 (1000),
salary NUMBER
);
TYPE name_salary_aat IS TABLE OF name_salary_rt
INDEX BY PLS_INTEGER;
l_employees name_salary_aat;
BEGIN
EXECUTE IMMEDIATE
q'[select first_name || ' ' || last_name, salary
from hr.employees
order by salary desc]'
BULK COLLECT INTO l_employees;
FOR indx IN 1 .. l_employees.COUNT
LOOP
DBMS_OUTPUT.put_line (l_employees (indx).name);
END LOOP;
END;
If I understand correctly, you want to create a query and execute it and return the result to another function or some calling app. As the resulting query's columns are note before-known, I'd return a ref cursor in this case:
create function get_sums return sys_refcur as
declare
my_cursor sys_refcursor;
v_query varchar2(32757);
begin
select
'select ' ||
listagg('sum(' || name_col || ')', ', ') within group (order by name_col) ||
' from another_tab'
into v_query
from tab_listcol;
open my_cursor for v_query;
return v_query;
end get_sums;
I need to write a procedure, which should return insert script for any given table dynamically. Below is the signature of the procedure.
P_export_data_dml(table_name IN, column_name IN, column_value IN, data_dml OUT)
Ex:
table T1
C1 | C2
---------- | ----------
10 | 20
10 | 21
table T2
C1 | C2 | C3
------- | ------- | --------
10 | 20 | 30
10 | 21 | 31
case1
Input:
P_export_data_dml(T1, C1, 10, data_dml)
Expected output:
Insert into T1(C1, C2) values(10,20);
Insert into T1(C1, C2) values(10,21);
case2
Input:
P_export_data_dml(T2, C1, 10, data_dml)
Expected output:
Insert into T2(C1, C2, C3) values(10, 20, 30);
Insert into T2(C1, C2, C3) values(10, 21, 31);
I am able to generate an insert statement when there is only one record in a table for given input. (Using all_tab_columns and then fetching given table for each column to form parts of the Insert statement, and then finally concatenating all the strings to form final INSERT statement).
But I am facing a challenge to form an insert statement when there are multiple records. Can you please help me with the logic to loop through the records and to form INSERT statement for all the records.
Try this procedure. Note that it is good for NUMBER, VARCHAR, DATE (when has a default format) data types
set serveroutput on
create or replace
procedure p_export_data_dml(p_table in varchar2, p_filter_column in varchar2, p_filter_value in varchar2, p_dmls in out varchar2)
is
cursor c_statements(p_table varchar2, p_filter_column varchar2, p_filter_value varchar2) is
select 'select ''insert into '||p_table||' ('||
listagg(column_name, ', ') within group (order by column_id) ||') values(''''''||'||
listagg(column_name, '||'''''', ''''''||') within group (order by column_id)||'||'''''');'' from '||p_table||' where '||p_filter_column||' = '''||p_filter_value||'''' insert_statement
from user_tab_columns
where table_name = upper(p_table);
v_output varchar2(4000);
v_sql varchar2(4000);
type t_cursor is ref cursor;
c_cur t_cursor;
begin
for r_statements in c_statements(p_table, p_filter_column, p_filter_value) loop
v_sql := r_statements.insert_statement;
dbms_output.put_line(v_sql);
open c_cur for v_sql;
loop
fetch c_cur into v_output;
exit when c_cur%notfound;
if p_dmls = null then
p_dmls := v_output;
else
p_dmls := p_dmls || '
'||v_output;
end if;
end loop;
close c_cur;
end loop;
end;
/
Then you can try executing using the below
declare
v_text varchar2(32000);
begin
p_export_data_dml('t1', 'c1', 10, v_text);
dbms_output.put_line(v_text);
end;
/
The output can be something like this:
insert into t1 (C1, C2, C3, C4) values('10', '1', '11', '12-SEP-2017 07:54:38');
insert into t1 (C1, C2, C3, C4) values('10', '2', '12', '12-SEP-2017 07:54:38');
insert into t1 (C1, C2, C3, C4) values('10', '3', '13', '12-SEP-2017 07:54:38');
It isn't clear from your question what data-type you are planning on using for data_dml OUT.
This could be a collection, or a clob, etc.
Please note, that most Oracle-supporting editors like SQL Developer, Intellij IDEA, TOAD, etc. already have this kind of thing built right in, with robust implementation to transform result sets into INSERTS.
That being said, this kind of thing can be achieved using Dynamic SQL.
Here are a couple light-weight examples, built on the premise you plan on using only NUMBERs for column_value params. Overloads could be added for others, or ANYDATA, as needed.
Example 1: This example will return multiple INSERT statements in a CLOB (a collection return type could be used instead). It will only generate INSERTs for NUMBER DATA_TYPE columns. Note no error handling here.
CREATE OR REPLACE PROCEDURE P_EXPORT_DATA_DML(P_TABLE_NAME IN VARCHAR2, P_COLUMN_NAME IN VARCHAR2, P_COLUMN_VALUE IN NUMBER, V_DATA_DML OUT CLOB)
IS
P_COLUMN_LIST CLOB;
V_VALUES_LIST CLOB;
TYPE USER_TAB_COL_TABLE IS TABLE OF USER_TAB_COLUMNS%ROWTYPE;
V_USER_TAB_COLS USER_TAB_COL_TABLE;
V_SELECTER_SQL_TEXT CLOB := '';
BEGIN
SELECT *
BULK COLLECT INTO V_USER_TAB_COLS
FROM USER_TAB_COLUMNS
WHERE USER_TAB_COLUMNS.TABLE_NAME = P_TABLE_NAME
AND USER_TAB_COLUMNS.DATA_TYPE IN ('NUMBER');
P_COLUMN_LIST := P_COLUMN_LIST || V_USER_TAB_COLS(1).COLUMN_NAME;
V_SELECTER_SQL_TEXT := V_SELECTER_SQL_TEXT || V_USER_TAB_COLS(1).COLUMN_NAME;
FOR POINTER IN 2..V_USER_TAB_COLS.COUNT
LOOP
P_COLUMN_LIST := P_COLUMN_LIST || ',' || V_USER_TAB_COLS(POINTER).COLUMN_NAME;
V_SELECTER_SQL_TEXT := V_SELECTER_SQL_TEXT || Q'!||','|| !' || V_USER_TAB_COLS(POINTER).COLUMN_NAME;
END LOOP;
V_SELECTER_SQL_TEXT := UTL_LMS.FORMAT_MESSAGE(Q'!SELECT LISTAGG('INSERT INTO %s !', P_TABLE_NAME) || '(' || P_COLUMN_LIST || Q'!) VALUES ( '||!' || V_SELECTER_SQL_TEXT || UTL_LMS.FORMAT_MESSAGE(Q'!||');'||CHR(10)||CHR(13) ) WITHIN GROUP (ORDER BY %s ASC) FROM !', P_COLUMN_NAME) || P_TABLE_NAME || ' WHERE ' || P_COLUMN_NAME || ' = ' || P_COLUMN_VALUE;
EXECUTE IMMEDIATE V_SELECTER_SQL_TEXT INTO V_DATA_DML;
END;
/
Then try it out for T1/C1:
DECLARE
V_RESULT CLOB;
BEGIN
P_EXPORT_DATA_DML('T1','C1',10,V_RESULT);
DBMS_OUTPUT.PUT_LINE(V_RESULT);
END;
/
INSERT INTO T1 (C1,C2) VALUES ( 10,20);
INSERT INTO T1 (C1,C2) VALUES ( 10,21);
PL/SQL procedure successfully completed.
Or for T2/C1:
DECLARE
V_RESULT CLOB;
BEGIN
P_EXPORT_DATA_DML('T2','C1',10,V_RESULT);
DBMS_OUTPUT.PUT_LINE(V_RESULT);
END;
/
INSERT INTO T2 (C1,C2,C3) VALUES ( 10,20,30);
INSERT INTO T2 (C1,C2,C3) VALUES ( 10,21,31);
PL/SQL procedure successfully completed.
Or for T2/C2:
...
P_EXPORT_DATA_DML('T2','C2',20,V_RESULT);
...
INSERT INTO T2 (C1,C2,C3) VALUES ( 10,20,30);
PL/SQL procedure successfully completed.
To support other DATA_TYPEs, you'll need to handle DATE/TIMESTAMP -> CHAR conversions, quoting CHARs, etc.
Here's an example that supports NUMBER + VARCHAR2
CREATE OR REPLACE PROCEDURE P_EXPORT_DATA_DML(P_TABLE_NAME IN VARCHAR2, P_COLUMN_NAME IN VARCHAR2, P_COLUMN_VALUE IN NUMBER, V_DATA_DML OUT CLOB)
IS
P_COLUMN_LIST CLOB;
V_VALUES_LIST CLOB;
TYPE USER_TAB_COL_TABLE IS TABLE OF USER_TAB_COLUMNS%ROWTYPE;
V_USER_TAB_COLS USER_TAB_COL_TABLE;
V_SELECTER_SQL_TEXT CLOB := '';
BEGIN
SELECT *
BULK COLLECT INTO V_USER_TAB_COLS
FROM USER_TAB_COLUMNS
WHERE USER_TAB_COLUMNS.TABLE_NAME = P_TABLE_NAME
AND USER_TAB_COLUMNS.DATA_TYPE IN ('NUMBER', 'VARCHAR2');
P_COLUMN_LIST := P_COLUMN_LIST || V_USER_TAB_COLS(1).COLUMN_NAME;
CASE WHEN V_USER_TAB_COLS(1).DATA_TYPE = 'NUMBER'
THEN
V_SELECTER_SQL_TEXT := V_SELECTER_SQL_TEXT || V_USER_TAB_COLS(1).COLUMN_NAME;
WHEN V_USER_TAB_COLS(1).DATA_TYPE = 'VARCHAR2'
THEN
V_SELECTER_SQL_TEXT := V_SELECTER_SQL_TEXT || Q'!''''||!' || V_USER_TAB_COLS(1).COLUMN_NAME || Q'!||''''!';
END CASE;
FOR POINTER IN 2..V_USER_TAB_COLS.COUNT
LOOP
P_COLUMN_LIST := P_COLUMN_LIST || ',' || V_USER_TAB_COLS(POINTER).COLUMN_NAME;
CASE WHEN V_USER_TAB_COLS(POINTER).DATA_TYPE = 'NUMBER'
THEN
V_SELECTER_SQL_TEXT := V_SELECTER_SQL_TEXT || Q'!||','|| !' || V_USER_TAB_COLS(POINTER).COLUMN_NAME;
WHEN V_USER_TAB_COLS(POINTER).DATA_TYPE = 'VARCHAR2'
THEN
V_SELECTER_SQL_TEXT := V_SELECTER_SQL_TEXT || Q'!||','|| !' || Q'!''''||!' || V_USER_TAB_COLS(POINTER).COLUMN_NAME || Q'!||''''!';
END CASE;
END LOOP;
V_SELECTER_SQL_TEXT := UTL_LMS.FORMAT_MESSAGE(Q'!SELECT LISTAGG('INSERT INTO %s !', P_TABLE_NAME) || '(' || P_COLUMN_LIST || Q'!) VALUES ( '||!' || V_SELECTER_SQL_TEXT || UTL_LMS.FORMAT_MESSAGE(Q'!||');'||CHR(10)||CHR(13) ) WITHIN GROUP (ORDER BY %s ASC) FROM !', P_COLUMN_NAME) || P_TABLE_NAME || ' WHERE ' || P_COLUMN_NAME || ' = ' || P_COLUMN_VALUE;
EXECUTE IMMEDIATE V_SELECTER_SQL_TEXT INTO V_DATA_DML;
END;
/
Test it out with a VARCHAR2 table:
CREATE TABLE T3 (C1 VARCHAR2(64), C2 NUMBER, C3 VARCHAR2(64));
INSERT INTO T3 VALUES ('XX',10,'AA');
INSERT INTO T3 VALUES ('XQ',10,'AQ');
INSERT INTO T3 VALUES ('XX',20,'AA');
Getting multiple rows:
DECLARE
V_RESULT CLOB;
BEGIN
P_EXPORT_DATA_DML('T3','C2',10,V_RESULT);
DBMS_OUTPUT.PUT_LINE(V_RESULT);
END;
/
INSERT INTO T3 (C1,C2,C3) VALUES ( 'XQ',10,'AQ');
INSERT INTO T3 (C1,C2,C3) VALUES ( 'XX',10,'AA');
PL/SQL procedure successfully completed.
Can you tell me what is wrong with this procedure that I'm trying to create?
CREATE OR REPLACE PROCEDURE create_audit_tables (table_owner VARCHAR2)
IS
CURSOR c_tables (
table_owner VARCHAR2)
IS
SELECT ot.owner AS owner, ot.table_name AS table_name
FROM all_tables ot
WHERE ot.owner = table_owner
AND ot.table_name NOT LIKE 'AUDIT_%'
AND ot.table_name <> 'EXAUDIT'
AND NOT EXISTS
(SELECT 1
FROM EXAUDIT efa
WHERE ot.table_name = efa.tname)
AND NOT EXISTS
(SELECT 1
FROM all_tables at
WHERE at.table_name = 'AUDIT_'||ot.table_name);
v_sql VARCHAR2 (8000);
v_count NUMBER := 0;
v_aud VARCHAR2 (30);
BEGIN
FOR r_table IN c_tables (table_owner)
LOOP
BEGIN
v_aud := 'AUDIT_'||r_table.table_name;
v_sql :=
'create table '
|| v_aud
|| ' as select * from '
|| r_table.owner
|| '.'
|| r_table.table_name
|| ' where 1 = 1';
DBMS_OUTPUT.put_line ('Info: ' || v_sql);
EXECUTE IMMEDIATE v_sql;
v_sql :=
'alter table '
|| v_aud
|| ' add ( AUDIT_ACTION char(1), AUDIT_BY varchar2(50), AUDIT_AT TIMESTAMP)';
EXECUTE IMMEDIATE v_sql;
v_count := c_tables%ROWCOUNT;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
'Failed to create table '
|| v_aud
|| ' due to '
|| SQLERRM);
END;
END LOOP;
IF v_count = 0
THEN
DBMS_OUTPUT.put_line ('No audit tables created');
ELSE
DBMS_OUTPUT.put_line (v_count || ' audit tables created.');
END IF;
END;
/
I checked it with show errors function and it gave me this:
LINE/COL ERROR
-------- --------------------------------------------
6/1 PL/SQL: SQL Statement ignored
16/3 PL/SQL: ORA-00906: missing left parenthesis
Perhaps the problem is quite simple, but I can't see it, so please help me if you can
I can compile procedure without problems after creating table
create table EXAUDIT (tname varchar2(100));
Check status of procedure:
select status from user_objects where lower(object_name) = 'create_audit_tables';
i have successfully implemented a proc which can delete delete duplicate records from a table .
Carrying on i am further trying to generalize this procedure using Dynamic sql But i get the following error when compiling itself .
ERROR line 13, col 7, ending_line 14, ending_col 14, Found ''SELECT ROWID, ERR_MOD
FROM '', Expecting: ( SELECT -or- WITH
Here is my code :-
CREATE OR REPLACE PROCEDURE BIOCON.proc_dedup (
p_tblname IN VARCHAR2,
p_cname IN varchar2,
p_cvalue IN varchar2,
p_out OUT VARCHAR2:=0
)
IS
v_cnt NUMBER;
CURSOR TMP
IS
'SELECT ROWID, ERR_MOD
FROM ' || p_tblname||
'WHERE '|| p_cname '='||''p_cvalue '';
BEGIN
BEGIN
'SELECT COUNT ( * )
INTO v_cnt
FROM ' || p_tblname||
'WHERE '|| p_cname' = '||''p_cvalue'';
EXCEPTION
WHEN OTHERS
THEN
p_out:=1;
end;
FOR REC IN tmp
LOOP
IF v_cnt = 1
THEN
EXIT;
ELSE
'DELETE FROM '|| p_tblname||
'WHERE ROWID = REC.ROWID';
END IF;
v_cnt := v_cnt - 1;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
p_out := 2;
END;
/
Hi you cannot create a dynamic query for normal cursors in such cases you should use ref cursors and follow the the steps below
--create a query string
--open the ref cursor
and please use execute immediate for execution of delete statements...
CREATE OR REPLACE PROCEDURE BIOCON.proc_dedup (
p_tblname IN VARCHAR2,
p_cname IN varchar2,
p_cvalue IN varchar2,
p_out OUT VARCHAR2:=0
IS
v_cnt NUMBER;
v_string varchar2(200);
TYPE ref_cur IS REF CURSOR
ref_cursor_name ref_cur;
BEGIN
v_string:='SELECT ROWID, ERR_MOD FROM ' || p_tblname|| 'WHERE '|| p_cname
'='||''p_cvalue '';
OPEN cursor_variable_name FOR v_string;
.....
.....
EXECUTE IMMEDIATE 'DELETE FROM '|| p_tblname|| 'WHERE ROWID = REC.ROWID';--you need execute immediate for this
.....
.....
I had return a program it will check which file is present or not and it will check no of column
create or replace procedure chkcsvfile
(P_UTLDIR VARCHAR2,
P_FILENAME VARCHAR2,
P_tabnam VARCHAR2
)
is
P_fieldel varchar2(2):= ',';
V1 VARCHAR2(32767) ;
P_errlen number :=0;
lv_a number;
lv_b number;
lv_c number;
lv_d number;
lv_check_file_exist boolean;
v_file utl_file.file_type;
cursor c1 is
select count(*) from user_tables where TABLE_NAME =P_tabnam;
cursor c2 is
select count(*) from user_tab_columns where TABLE_NAME =P_tabnam;
begin
open c1;
fetch c1 into lv_c;
if lv_c = 0 then
dbms_output.put_line('table name is invalid : ' || P_tabnam);
end if;
--'test wheather file is available or not'
dbms_output.put_line ('test wheather file is available or not');
utl_file.fgetattr (P_UTLDIR,P_FILENAME, lv_check_file_exist, lv_a, lv_b );
if lv_check_file_exist then
dbms_output.put_line('file ' ||P_FILENAME ||' exists');
v_file := utl_file.fopen(P_UTLDIR,P_FILENAME, 'R');
UTL_FILE.get_line (v_file ,V1,32767);
DBMS_OUTPUT.put_line ('V1 :' || V1);
if (REGEXP_like (V1, ',',1))
then
P_errlen := P_errlen +1 ;
dbms_output.put_line ('errrooooooooooooooooooooooooooooooooooorr');
dbms_output.put_line (P_errlen );
end if;
end if;
if not lv_check_file_exist then
dbms_output.put_line('file ' || P_FILENAME ||' does not exist');
end if;
if lv_check_file_exist is null then
dbms_output.put_line('file check null');
end if;
if lv_check_file_exist is not null then
dbms_output.put_line('file check not null');
end if;
dbms_output.put_line('lv_a-->'||lv_a);
dbms_output.put_line('lv_b-->'||lv_b);
open c2;
fetch c2 into lv_d;
dbms_output.put_line ('No of columns in a table : ' || lv_d );
end;
/
NOW my problem is i have to match " , " in a string and i want the count of it . i had written the program but it not give me specific count .
data in string is given in below format
7839,KING ,PRESIDENT,0000,17-nov-1981, 005000.00 ,000000.00,10,
please help me
thanks in advance
Since you're using 11g, you can use the regexp_count function.
select regexp_count('7839,KING ,PRESIDENT,0000,17-nov-1981, 005000.00 ,000000.00,10,',',')
from dual