Creation of table through execute immediate
Im trying to create a table through the following procedure.
create or replace procedure tab_creat
v_sql_Stmt varchar2(100);
begin
v_sql_stmt:='create table test_prc (num number)';
execute immediate v_sql_stmt;
end;
The procedure is getting compiled but it is not getting executed.
Im getting the following error.
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "SCOTT.TAB_CREAT", line 6
ORA-06512: at line 1
I also gave the DBA privilleges for the particular schema but still im getting the following error
1) Creating a table (or any object) dynamically in a stored procedure is almost always a bad idea in Oracle.
2) Stored procedures (of the default definer's rights variety) do not have access to privileges granted through a role. The procedure owner would need to have the CREATE TABLE privilege granted directly to him, not granted via a role.
Justin
Similar Messages
-
Selecting data from a table using Execute Immediate in 9i
Hi,
I was wondering how I would be able to do a SELECT on a table using EXECUTE IMMEDIATE. When I tried it (with the proc below), I got the following below. Can anyone tell me what I am doing wrong?
Using Scott/Tiger I tried this:
SQL> ed
Wrote file afiedt.buf
1 CREATE OR REPLACE PROCEDURE P2
2 IS
3 v_SQL VARCHAR2(100);
4 BEGIN
5 v_SQL := 'Select * from Emp';
6 EXECUTE IMMEDIATE v_SQL;
7* END;
SQL> /
Procedure created.
SQL> exec p2
PL/SQL procedure successfully completed.
SQL> set serveroutput on
SQL> exec p2
PL/SQL procedure successfully completed.
SQL>
Thanks in advance.
Sincerely,
Nikhil Kulkarni1 CREATE OR REPLACE PROCEDURE P2
2 IS
3 v_SQL VARCHAR2(100);
erec emp%rowtype;
4 BEGIN
5 v_SQL := 'Select * from Emp';
6 EXECUTE IMMEDIATE v_SQL into erec;
7* END;
SQL> / -
Create temp table using EXECUTE IMMEDIATE
Is there any performance issue in creating globally temp table
using EXECUTE IMMEDIATE or creating globally temp table from
SQL PLUS.
Any response will be greatly appreciated.
nullAnish,
Creating tables is likely to be an expensive operation.
Performance issues can only be considered in comparison to
alternatives.
Alternatives include: PLSQL tables, cursors and/or recoding so
that tmp tables are not required. (One of our consultants reckons
that sqlserver temp tables are usually used to get around
limitations in sqlserver, ie slightly more complicated sql
statements could be used instead of simpler sql and temporary
tables).
I would think creating the temp table once during sqlplus would
be cheaper than creating and deleting it repeatedly at run time.
Note that EXECUTE IMMEDIATE may do an implicit commit (dbms_sql
certainly does). This may be got over my using the PRAGMA
AUTONOMOUS_TRANSACTION; direction which places a
procedure/function in a seperate transaction.
Turloch
P.S. We have some difficulty in getting information back from the
field/customer sites. If you have questions and answers that are
likely to be useful to other Oracle Migration Workbench
users, and migrators in general, please send them in for possible
inclusion in our Frequently Asked Question list.
Oracle Migration Workbench Team
Anish (guest) wrote:
: Is there any performance issue in creating globally temp table
: using EXECUTE IMMEDIATE or creating globally temp table from
: SQL PLUS.
: Any response will be greatly appreciated.
Oracle Technology Network
http://technet.oracle.com
null -
CREATE TEMPORARY TABLE USING EXECUTE IMMEDIATE
Hi All,
i have a question,
how can i create a temporary table using EXECUTE IMMEDIATE ??
Like:
CREATE GLOBAL TEMPORARY table new_table as (Select * from old_table);
Thanks,
Edited by: xDeviates on Jun 11, 2012 3:13 PMIt looks like you are approaching the problem incorrectly. As I suggested in Dynamic Select, it sounds like you, at most, want a function that returns a SYS_REFCURSOR (it's still not obvious to me why you would even want/ need to resort to dynamic SQL in the first place)
CREATE OR REPLACE FUNCTION get_dynamic_cursor( p_table_name IN VARCHAR2 )
RETURN sys_refcursor
IS
l_rc sys_refcursor;
BEGIN
OPEN l_rc FOR 'SELECT * FROM ' || dbms_assert.sql_object_name( p_table_name );
RETURN l_rc;
END;which you can then call from your application
SQL> variable rc refcursor;
SQL> exec :rc := get_dynamic_cursor( 'EMP' );
PL/SQL procedure successfully completed.
SQL> print rc
EMPNO ENAME JOB MGR HIREDATE SAL COMM
DEPTNO
7369 SMITH CLERK 7902 17-DEC-80 801
20
7499 ALLEN SALESMAN 7698 20-FEB-81 1601 300
30
7521 WARD SALESMAN 7698 22-FEB-81 1251 500
30
EMPNO ENAME JOB MGR HIREDATE SAL COMM
DEPTNO
7566 JONES MANAGER 7839 02-APR-81 2976
20
7654 MARTIN SALESMAN 7698 28-SEP-81 1251 1400
30
7698 BLAKE MANAGER 7839 01-MAY-81 2851
30
EMPNO ENAME JOB MGR HIREDATE SAL COMM
DEPTNO
7782 CLARK MANAGER 7839 09-JUN-81 2451
10
7788 SCOTT ANALYST 7566 19-APR-87 3001
20
7839 KING PRESIDENT 17-NOV-81 5001
10
EMPNO ENAME JOB MGR HIREDATE SAL COMM
DEPTNO
7844 TURNER SALESMAN 7698 08-SEP-81 1501 0
30
7876 ADAMS CLERK 7788 23-MAY-87 1101
20
7900 JAMES CLERK 7698 03-DEC-81 951
30
EMPNO ENAME JOB MGR HIREDATE SAL COMM
DEPTNO
7902 FORD ANALYST 7566 03-DEC-81 3001
20
7934 MILLER CLERK 7782 23-JAN-82 1301
10
14 rows selected.Justin -
Problem with alter table in execute immediate
We have PL/SQL scripts which modify the data structure, add data etc to en existing database. These scripts basically ensure that the db is compatible with what the software expects.
The reason for doing it in PL/SQL rather than SQL script is A) The scripts are launched using GUI so that they are more user friendly. sqlplus is launched as a background process which executes these scripts. All the scripts have EXIT FAILURE WHENEVER SQLERROR as first line to ensure that the control does not hang in the sqlplus background process.
Going from one version to other, we have added a few tables to the database and also modified a few tables. since (i think) DDL is not allowed in PL/SQL block, we had to resort to putting them in EXECUTE IMMEDIATE enclosures.
Now for the real question,
If I create a table using EXECUTE IMMEDIATE clause, I can immediately have insert as a next statement to insert data in this table. but, if I alter the table and add a column to the existing table, I cannot immediately add data to that column, it throws an error saying 'invalid identifier'
At code level, the following is allowed :
EXECUTE IMMEDIATE 'CREATE TABLE SP_TEST_TABLE
ID NUMBER,
NAME Varchar2(40)
INSERT INTO SP_TEST_TABLE(ID, NAME) Values(1, 'SP');
but I get error for the following :
EXECUTE IMMEDIATE 'ALTER TABLE SP_TEST_TWO ADD
ANOTHER_COLUMN number
UPDATE SP_TEST_TWO SET ANOTHER_COLUMN = 1;
In this case, it says ANOTHER_COLUMN invalid identifier
Does anybody know why?
any workaround will be greatly appreciated.
--SPFriends,
Thanks to all of you for your help. The spelling mistakes might have occurred becuase i changed the actual script to something 'short and complete' to show the problem.
I could solve the problem by having more than one PL/SQL block within my file. something like :
BEGIN
--alter table statements here
END;
BEGIN
--insert the values in column here.
END;
I am still not sure why the error is presented only on alter table statement and not for create table statement. Probably somebody with the knowledge of oracle internals will be able to throw more light on it. I am trying to get the naswers, if I get the answer, I'll surely post it here.
Regards,
--Saurabh -
Oracle 11G Copying a table using execute immediate
I want to copy the contents of one table into another using execute immediate.
This keeps failing with the following error
ORA-00903: invalid table name
ORA-06512: at "TABLE_COPY", line 6
ORA-06512: at line 8
create or replace
procedure TABLE_COPY(
TABLE1 varchar2,
TABLE2 varchar2)
is
begin
execute immediate 'insert into '||TABLE2||' (select * from '||TABLE1||')';
end;
Edited by: user9213000 on 24-Jan-2013 07:38user9213000 wrote:
I want to copy the contents of one table into another using execute immediate.
This keeps failing with the following error
ORA-00903: invalid table name
ORA-06512: at "TABLE_COPY", line 6
ORA-06512: at line 8
create or replace
procedure TABLE_COPY(
TABLE1 varchar2,
TABLE2 varchar2)
is
begin
execute immediate 'insert into '||TABLE2||' (select * from '||TABLE1||')';
end;
Edited by: user9213000 on 24-Jan-2013 07:38The standard advice when (ab)using EXECUTE IMMEDIATE is to compose the SQL statement in a single VARCHAR2 variable
Then print the variable before passing it to EXECUTE IMMEDIATE.
COPY the statement & PASTE into sqlplus to validate its correctness. -
Problem in using CREATE TABLE with Execute Immediate
I'm trying to create a table using Native Dynamic SQL. the code of the pl/sql block is
BEGIN
EXECUTE IMMEDIATE 'create table demo (ddate date)';
END;
The problem is that the above block is executed successfully as an anonymous PL/SQL block. The same block when written in a procedure it gives an error
"ORA-01031 Insufficient privelages"
at the time of execution. The procedure is complied successfully.
nullYour user needs direct system privs to create tables. You are receiving your privs properly by the role RESOURCE. Connect as system and grant CREATE TABLE directly to your user - that should do it.
Regards
Peter Larsen -
PLSQL table in EXECUTE IMMEDIATE
Hi All,
This is just a sample code.Table name may be changed in next run.
when I run this program ,getting error in EXECUTE IMMEDIATE -" V_FIELDS invalid identifier",Also the way I am doing,that's right?
create table TEMP
col1 VARCHAR2(200),
col2 VARCHAR2(200),
col3 DATE )
DECLARE
v_fields dbms_sql.varchar2a;
v_col_str VARCHAR2(200);
v_insert VARCHAR2(200);
v_idx INTEGER := 0;
v_tab VARCHAR2(30) := 'TEMP';
BEGIN
FOR i IN (SELECT s.column_name, s.data_type
FROM user_tab_cols s
WHERE s.table_name = v_tab
ORDER BY s.column_id)
LOOP
v_col_str := v_col_str || i.column_name || ',';
IF i.data_type = 'DATE'
THEN
v_insert := v_insert || 'TO_DATE(v_fields(' || v_idx || '),' ||
'''MM/DD/YYYY''' || '),';
ELSE
v_insert := v_insert || 'v_fields(' || v_idx || '),';
END IF;
v_idx := v_idx + 1;
END LOOP;
v_insert := '( ' || RTRIM(v_insert, ',') || ' )';
v_col_str := 'INSERT INTO ' || v_tab || ' ( ' || RTRIM(v_col_str, ',') ||
' ) VALUES ';
dbms_output.put_line(v_col_str || v_insert);
v_fields(0) := 1;
v_fields(1) := 'AB';
v_fields(2) := SYSDATE;
EXECUTE IMMEDIATE v_col_str || v_insert;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('Err: ' || SQLERRM);
END;
Thanks,The dynamic SQL generated is
INSERT INTO TEMP ( COL1,COL2,COL3 ) VALUES ( v_fields(0),v_fields(1),TO_DATE(v_fields(2),'MM/DD/YYYY') ) PL/SQL engine sends this SQL to SQL engine. And guess what, SQL Engine has no clue what v_fields is. Why? because v_fields a private variable defined in a PL/SQL block for which SQL Engine has zero access.
Try this
DECLARE
v_fields dbms_sql.varchar2a;
v_col_str VARCHAR2(200);
v_insert VARCHAR2(200);
v_idx INTEGER := 0;
v_tab VARCHAR2(30) := 'TEMP';
BEGIN
FOR i IN (SELECT s.column_name, s.data_type
FROM user_tab_cols s
WHERE s.table_name = v_tab
ORDER BY s.column_id)
LOOP
v_col_str := v_col_str || i.column_name || ',';
IF i.data_type = 'DATE'
THEN
v_insert := v_insert || 'TO_DATE(:' || v_idx || ',' ||
'''MM/DD/YYYY''' || '),';
ELSE
v_insert := v_insert || ':' || v_idx || ',';
END IF;
v_idx := v_idx + 1;
END LOOP;
v_insert := '( ' || RTRIM(v_insert, ',') || ' )';
v_col_str := 'INSERT INTO ' || v_tab || ' ( ' || RTRIM(v_col_str, ',') ||
' ) VALUES ';
v_fields(0) := 1;
v_fields(1) := 'AB';
v_fields(2) := to_char(SYSDATE, 'MM/DD/YYYY');
execute immediate v_col_str || v_insert using v_fields(0), v_fields(1), v_fields(2);
END;
/ I personally don't encourage dynamic SQL. Dynamic SQL is always a pain and a result of bad design.
And the most worst thing, the thing that is terrible than dynamic SQL is this
WHEN OTHERS THEN
dbms_output.put_line('Err: ' || SQLERRM);
END; Whats the logic and possible benefit behind this code? Its NONE. Don't do that, NEVER. WHEN OTHERS without a RAISE is a bug in your code. So never do that. And DBMS_OUTPUT is not the correct way to render error message to user. -
Inserting variables to table by "execute immediate' statement
EXECUTE IMMEDIATE 'INSERT INTO aTABLETKA_HISTORY
(update_id,
update_type,
update_date,
old_db_version,
description,
patch_number)
values
(' || m_id(v_rec) || ',
'||m_package(v_rec)||',
''07-NOV-07'',
''snezi'',
'||m_desc(v_rec)||',
'||m_new(v_rec)||')';
ORA-00917: missing comma
ORA-06512: at line 142
i cannot solve this,. can anybody help me?
i have simillar insert:
EXECUTE IMMEDIATE 'INSERT INTO ab_table_VERSION(property,version) values (''wiz_datalink'',' || my_version || ')';
and this one statement work correctlyDo NOT use "execute immediate". What is the reason for trying it this way?
If the column update_date is of type date, then you have a bug in the code, as you are trying to insert a string. If it is not a date data type, then you have a bug, because it is not of type date.
What is the outcome of:
INSERT INTO aTABLETKA_HISTORY (update_id, update_type, update_date,
old_db_version, description, patch_number)
values (m_id(v_rec), m_package(v_rec), to_date('07-NOV-2007', 'dd-MON-yyyy'),
snezi, m_desc(v_rec), m_new(v_rec) )
/ -
CREATE TABLE #check(
reseller_account_id bigint NOT NULL PRIMARY KEY
,customer_id int NOT NULL
INSERT INTO #check(reseller_account_id, customer_id)
SELECT reseller_account_id, customer_id
FROM ods.derived.postal_accounts pa
JOIN ods.derived.bridge_accounts ba
ON pa.bridge_id = ba.bridge_id
AND pa.primary_multi_user_account_flag = 1
WHERE promotion_code LIKE 'England-[01234]'
AND reseller_account_id > 0;
SELECT [reseller_id]
,c.reseller_account_id
,t.[postage_id]
,t.[customer_id]
,t.[mail_class_id]
,[mail_class_name]
,[mail_type_id]
,[mail_type_description]
,[org_zip_code]
,[dest_zip_code]
,[zone]
,t.[confirmation_number]
,[weight_category]
,[usps_postage_amount]
,[reseller_postage_amount]
,[cubic_pricing_flag]
,[destination_address]
,pe.recipient_address
FROM ods.derived.v_reseller_prints_for_export t(NOLOCK)
JOIN check_test c
ON c.customer_id=t.customer_id
JOIN ods.swsim.prints s(NOLOCK)
ON t.postage_id=s.postage_id
JOIN ods.postal.prints_extension pe(NOLOCK)
on pe.postage_id=s.postage_id
where t.customer_id IN (Select customer_id from #check)Hi Mark Subedi,
In addtion to the above posts.
The fragment referenced from the BOL
You can create local and global temporary tables. Local temporary tables are visible only in the current session; global temporary tables are visible to all sessions.
All local temporary tables are dropped automatically at the end of the current session.
You can read more from the below link.
https://technet.microsoft.com/en-us/library/aa258255(v=sql.80).aspx
If you have any question, feel free to let me know.
Eric Zhang
TechNet Community Support -
Pipelined Function with execute immediate
Hello Experts,
I have created a Pipe lined function with execute immediate, due to below requirement;
1) Columns in where clause is passed dynamically.
2) I want to know the data stored into above dynamic columns.
3) I want to use it in report, so I don't want to insert it into a table.
I have created a TYPE, then through execute immediate i have got the query and result of that query will be stored in TYPE.
But when calling the function i am getting
ORA-00932: inconsistent datatypes: expected - got -
Below is my function and type, let me know i am going wrong, and is my logic correct.
CREATE OR REPLACE TYPE OBJ_FPD AS OBJECT
(LOW_PLAN_NO VARCHAR2 (40),
FPD VARCHAR2 (5),
SERIAL_NO NUMBER,
CEDIA_CODE VARCHAR2 (2),
DT DATE);
CREATE OR REPLACE TYPE FPD_TBL_TYPE AS TABLE OF OBJ_FPD;
CREATE OR REPLACE FUNCTION FUNC_GET_FPD_DATE (P_LOW_PLAN_NO VARCHAR2,
P_CEDIA_CODE VARCHAR2,
P_SERIAL_NO NUMBER)
RETURN FPD_TBL_TYPE
PIPELINED
AS
CURSOR C1
IS
SELECT 'FPD' || LEVEL TBL_COL
FROM DUAL
CONNECT BY LEVEL <= 31;
V_STR VARCHAR2 (5000);
V_TBL_TYPE FPD_TBL_TYPE;
BEGIN
FOR X IN C1
LOOP
V_STR :=
'SELECT A.low_PLAN_NO,
A.FPD,
A.SERIAL_NO,
A.cedia_code,
TO_DATE (
SUBSTR (FPD, 4, 5)
|| ''/''
|| TO_CHAR (C.low_PLAN_PERIOD_FROM, ''MM'')
|| ''/''
|| TO_CHAR (C.low_PLAN_PERIOD_FROM, ''RRRR''),
''DD/MM/RRRR'')
DT FROM ( SELECT low_PLAN_NO, '
|| ''''
|| X.TBL_COL
|| ''''
|| ' FPD, '
|| X.TBL_COL
|| ' SPTS, SERIAL_NO, cedia_code FROM M_low_PLAN_DETAILS WHERE NVL('
|| X.TBL_COL
|| ',0) > 0 AND SERIAL_NO = '
|| P_SERIAL_NO
|| ' AND cedia_code = '
|| ''''
|| P_CEDIA_CODE
|| ''''
|| ' AND low_PLAN_NO = '
|| ''''
|| P_LOW_PLAN_NO
|| ''''
|| ') A,
M_low_PLAN_DETAILS B,
M_low_PLAN_MSTR C
WHERE A.low_PLAN_NO = B.low_PLAN_NO
AND A.cedia_code = B.cedia_code
AND A.SERIAL_NO = B.SERIAL_NO
AND B.low_PLAN_NO = C.low_PLAN_NO
AND B.CLIENT_CODE = C.CLIENT_CODE
AND B.VARIANT_CODE = C.VARIANT_CODE
CONNECT BY LEVEL <= SPTS';
EXECUTE IMMEDIATE V_STR INTO V_TBL_TYPE;
FOR I IN 1 .. V_TBL_TYPE.COUNT
LOOP
PIPE ROW (OBJ_FPD (V_TBL_TYPE (I).LOW_PLAN_NO,
V_TBL_TYPE (I).FPD,
V_TBL_TYPE (I).SERIAL_NO,
V_TBL_TYPE (I).CEDIA_CODE,
V_TBL_TYPE (I).DT));
END LOOP;
END LOOP;
RETURN;
EXCEPTION
WHEN OTHERS
THEN
RAISE_APPLICATION_ERROR (-20000, SQLCODE || ' ' || SQLERRM);
RAISE;
END;Waiting for your views.
Regards,Ora Ash wrote:
Hello Experts,
I have created a Pipe lined function with execute immediate, due to below requirement;
1) Columns in where clause is passed dynamically.No, that's something you've introduced, and is due to poor database design. You appear to have columns on your table called FPD1, FPD2 ... FPD31. The columns do not need to be 'passed dynamically'
2) I want to know the data stored into above dynamic columns.And you can know the data without it being dynamic.
3) I want to use it in report, so I don't want to insert it into a table.That's fine, though there's no reason to use a pipelined function.
You also have an pointless exception handler, which masks any real errors.
I'm not quite sure what the point of your "connect by" is in your query as we don't have your tables or data or know for sure what the expected output is.
However, in terms of handling the 'dynamic' part that you've introduced, then you would be looking at doing something along the following lines, using a static query that requires no poor dynamic code, and no pipelined function...
with x as (select level as dy from dual connect by level <= 31)
select a.low_plan_no
,a.fpd
,a.serial_no
,a.cedia_code
,trunc(c.low_plan_period_from)+a.dy-1 as dt
from (select low_plan_no
,dy
,'FPD'||dy as fpd
,spts
,serial_no
,cedia_code
from (
select low_plan_no
,x.dy
,case x.dy when 1 then fpd1
when 2 then fpd2
when 3 then fpd3
when 4 then fpd4
when 5 then fpd5
when 6 then fpd6
when 7 then fpd7
when 8 then fpd8
when 9 then fpd9
when 10 then fpd10
when 11 then fpd11
when 12 then fpd12
when 13 then fpd13
when 14 then fpd14
when 15 then fpd15
when 16 then fpd16
when 17 then fpd17
when 18 then fpd18
when 19 then fpd19
when 20 then fpd20
when 21 then fpd21
when 22 then fpd22
when 23 then fpd23
when 24 then fpd24
when 25 then fpd25
when 26 then fpd26
when 27 then fpd27
when 28 then fpd28
when 29 then fpd29
when 30 then fpd30
when 31 then fpd31
else null
end as spts
,serial_no
,cedia_code
from x cross join m_low_plan_details
where serial_no = p_serial_no
and cedia_code = p_cedia_code
and low_plan_no = p_low_plan_no
where nvl(spts,0) > 0
) A
join m_low_plan_details B on ( A.low_plan_no = B.low_plan_no
and A.cedia_code = B.cedia_code
and A.serial_no = B.serial_no
join m_low_plan_mstr C on ( B.low_plan_no = C.low_plan_no
and B.client_code = C.client_code
and B.variant_code = C.variant_code
connect by level <= spts;... so just remind us again why you think it needs to be dynamic? -
EXECUTE IMMEDIATE ORA-01722 invalid number
hi all
i have a plsql procedure in which the following statement which gives this error ORA-01722: invalid number
sql_stmt :='UPDATE Student set '||stu_gradefor||'=TO_NUMBER('||stu_marks||') where UserID='||stu_UID;
EXECUTE IMMEDIATE sql_stmt;
here all variables (stu_marks,stu_gradefor and stu_UID) are varchar2 coming from different procedure(form) but in the table named Student column HW1 (stu_gradefor) is of datatype number.
I have tried a lot but could not make it to work. Is it that we cannot enter an number through EXECUTE IMMEDIATE? If Possible can somebody help me with this?
Thanks a lot.
Regards
Jyoticreate table Student(UserID varchar2(8) not null, HW1 number(3) , HW2 number(3) , PA1 number(3) , ................);
create table Domain(R_Domain varchar2(11) not null, R_Status char(1) not null, R_Date Date null,R_Value varchar2(11) null, R_Mean varchar2(300) not null);
insert into Domain( R_Domain, R_Status, R_Value, R_Mean )values(
'Term','t','PA1','First Programming Assignment');
Full names for HW1, HW2, PA1....are in the Domain table. so in variable stu_gradefor we get the R_Value.
this is true :variable stu_marks is not actually a number, so the TO_NUMBER is causing the error. stu_marks is of datatype varchar2 but the field HW1,.. are all expecting a numeric value.
i tried SELECT TO_NUMBER(stu_marks) INTO gmark FROM DUAL;
sql_stmt :='UPDATE Student set '||stu_gradefor||'=(:1) where UserID='||stu_UID;
EXECUTE IMMEDIATE sql_stmt using gmark;
where gmark is a number but noting works.same error
This can be true:the column userid is a varchar2 column with a mix of numeric and alpha numeric values. userid value that i inserted was'12345678'
i there any other way to handle this situation?
Thanks for replying
Jyoti -
Problems using DDL & EXECUTE IMMEDIATE in package
Hi...
I have an 8i package in which I am trying to execute some DDL via EXECUTE IMMEDIATE to create temporary tables from which I then populate a REF_CURSOR by selecting from the last table created in the DDL. The problem is that the compiler doesn't seem to like the DDL.
Here's what I'm using:
CREATE OR REPLACE PACKAGE BODY NEREP_REF
AS
Procedure GetNE_REF (
i_Node IN VARCHAR2,
io_cursor IN OUT t_cursor )
IS
sql_stmt varchar2(200);
v_cursor t_cursor;
BEGIN
sql_stmt := 'CREATE TABLE tmp AS SELECT * FROM nerep4;';
EXECUTE IMMEDIATE sql_stmt;
OPEN v_cursor FOR
SELECT NE_Node, NE_Type, EHA, Status, Curr_Func, TP_Name,
Order_Item_Name, Required_Start, Required_End, Trail_Name
FROM tmp
WHERE NE_Node = i_Node ;
io_cursor := v_cursor;
END GetNE_REF;
END NEREP_REF;
The problem is that when I compile the package I get the errors below:
SQL> @sp_nerep_body
Warning: Package Body created with compilation errors.
SQL> show err
Errors for PACKAGE BODY NEREP_REF:
LINE/COL ERROR
20/7 PL/SQL: SQL Statement ignored
23/14 PLS-00201: identifier 'NE_NODE' must be declared
So it seems that it doesn't like the DDL (have I got the sql_stmt assignment in the wrong place maybe?) and then it complains it can't find the columns, which is reasonable because of course it doesn't know that the table 'tmp' comes from the result of the DDL statement!
If I change the table name in the 'OPEN v_cursor FOR' select clause to a table that already exists (ie: not created in this package) it runs just fine and I get the data I asked for... the problem is that I need to create this table on the fly by using DDL in my package!
This is driving me crazy - basically I need to be able to execute DDL to do various 'create table ... as select ... from ...' statements which eventually builds a final table which I then want to populate using a REF_CURSOR so I can return the results back to ASP via ADO... but I just can't get the DDL bit to work no matter what I try!!
Can anyone see what I'm doing wrong here?
Mike.
nullHere are a some ideas to try:
Remove the extra semicolon from your sql_stmt, so that line reads:
sql_stmt := 'CREATE TABLE tmp AS SELECT * FROM nerep4';
Ensure that you have proper privileges as an individual user, not just through a role, by:
connecting to the database using username system and password manager and granting yourself the proper privileges. For example, if you are user SCOTT, then:
SQL> GRANT CREATE TABLE TO SCOTT;
Then, exit and connect as yourself and try to compile and execute your procedure again.
If that still doesn't work, try testing one little piece at a time until you can identify the part that causes trouble. For example, start with a procedure that does nothing but try to create the tmp table using execute immediate, then add the other pieces, then try to put the procedure in a package. -
Unable to INSERT PL/SQL record with EXECUTE IMMEDIATE
Hi All,
I am selecting data from a source table and after some modification inserting into a target table. Source and target table name are available at run time. You can say only source table structure is fixed.
I have crated a pl/sql table of type source record and inserting record by record in target table using execute immediate. But I am not able to write
EXECUTE IMMEDIATE string USING pl_sql_table(index); and getting error as
PLS-00457: expressions have to be of SQL types
Please see the part of code below. Is it possible to use FORALL with dynamic sql like
FORALL pl_sql_table.FIRST .. pl_sql_table.COUNT
EXECUTE IMMEDIATE .... pl_sql_table(j); -- Like this.
Please suggest why I am not able to write record here. I also want to replace 'INSERT in a loop' with a single INSERT statement out of the loop, to upload whole pl_sql table into target table in one go.
Thanks,
Ravi
DECLARE
TYPE rec_tab_CMP IS RECORD
model_id NUMBER(38),
absolute_rank NUMBER(5)
v_rec_tab_CMP rec_tab_CMP;
TYPE t_rec_tab_CMP IS TABLE OF v_rec_tab_CMP%TYPE INDEX BY BINARY_INTEGER;
v_records_CMP t_rec_tab_CMP;
rc SYS_REFCURSOR;
v_old_table_name VARCHAR2(30); -- passed from parameter
v_new_table_name VARCHAR2(30); -- passed from parameter
dyn_str VARCHAR2(500);
v_columns_str VARCHAR2(200) := ' model_id, absolute_rank ';
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE '|| v_new_table_name || ' AS SELECT * FROM ' || v_old_table_name ||' WHERE 1 = 2 ' ;
OPEN rc FOR 'SELECT '|| v_columns_str ||' FROM '|| v_old_table_name;
FETCH rc BULK COLLECT INTO v_records_CMP;
FOR j IN 1..v_records_CMP.COUNT
LOOP
v_records_CMP(j).model_id := 1; -- Do someting here, This thing can be performed in SQL stmt directly.
dyn_str := 'INSERT INTO '|| v_new_table_name ||' ( '|| v_columns_str || ' ) VALUES (:1, :2) ';
EXECUTE IMMEDIATE dyn_str USING v_records_CMP(j).model_id ,
v_records_CMP(j).absolute_rank ;
-- Here in place of two columns I want to use one record like
-- EXECUTE IMMEDIATE dyn_str USING v_records_CMP(j);
-- But it is giving me error like
-- EXECUTE IMMEDIATE dyn_str USING v_records_st(j);
-- PLS-00457: expressions have to be of SQL types
END LOOP;
CLOSE rc;
END;
/You cannot bind PL/SQL record types to dynamic SQL.
Possibly you could work around this by declaring the INDEX-BY table of records at package specification level, e.g.
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
SQL> CREATE PACKAGE package_name
2 AS
3 TYPE tt_emp IS TABLE OF emp%ROWTYPE;
4 t_emp tt_emp;
5 END package_name;
6 /
Package created.
SQL> CREATE TABLE new_emp
2 AS
3 SELECT *
4 FROM emp
5 WHERE 1 = 0;
Table created.
SQL> DECLARE
2 v_table_name user_tables.table_name%TYPE := 'NEW_EMP';
3 BEGIN
4 SELECT *
5 BULK COLLECT INTO package_name.t_emp
6 FROM emp;
7
8 EXECUTE IMMEDIATE
9 'BEGIN ' ||
10 ' FORALL i IN 1 ..package_name.t_emp.COUNT ' ||
11 ' INSERT INTO ' || v_table_name ||
12 ' VALUES package_name.t_emp (i); ' ||
13 'END;';
14 END;
15 /
PL/SQL procedure successfully completed.
SQL> SELECT empno, ename
2 FROM new_emp;
EMPNO ENAME
7369 SMITH
7499 ALLEN
7521 WARD
7566 JONES
7654 MARTIN
7698 BLAKE
7782 CLARK
7788 SCOTT
7839 KING
7844 TURNER
7876 ADAMS
7900 JAMES
7902 FORD
7934 MILLER
14 rows selected.
SQL> -
I need to update certain columns of a table .
But the columns are dynamic. i can update 1,20r 3 or more columns of that table.
I tried executing with the Execute immediate statement.
But i am getting the error (ORA-01747)
:1(below in code) Contains the column name along with the values. (Example:Column2=Column2.value,Column3=Column3.value)
There can be more than 3 or more columns to be updated.
CREATE OR REPLACE PROCEDURE PR_Bulk_CA(pn_SSCA_ID_VARRAY BULK_UPDATE_CA_VARRAY
,pv_set_string Varchar2
,pn_success OUT number
Is
sql_stmt VARCHAR2(32000);
BEGIN
sql_stmt:= 'update table_A
SET :1
WHERE ID IN (select ID from table_A ca
where ca.status in (20700,20710,20720)
and ca.id in (select * from table(:2)))';
EXECUTE IMMEDIATE sql_stmt USING pv_set_string,pn_SSCA_ID_VARRAY;
COMMIT;
pn_success:=0;
EXCEPTION
WHEN OTHERS THEN
pn_success:=-1;
END PR_Bulk_CA;So?
By concatenating the column-name-update-string to the rest of the dynamic statement you get what you want.
if your pv_set_string has:
column_a = 17, column_b = 15, column_c = 12in it, the statement generated will handle this...
I did not state not to do dynamic sql but not to pass the column names using bind variables, as this will not work. The reason therefore is, that the parser need to know the names of the columns to figure out, whether you passed a syntactical correct statement. The parser will not know the content of a bind variable as this is not needed for the syntax (and access rights) check.
hth
Maybe you are looking for
-
HP Laser Jet 5000 Postscript PS Drivers not working
I have a Laser Jet 5000. No major problems for a few years until my system recently got a virus and had to be wiped clean. My PS printing no longer works. It says it is installed, but when I go to use it to print I only get error messages and no p
-
I have been given a leaflet to adjust which is in pdf format. After alterations I resaved the pdf and printed a sample but the print now has a white border around it. Why have the dimensions changed?? Or what has happened? Please help.
-
I backed up my viber messages, so my question is when I restore them on my new ipho
-
IPhone 2G Wi-fi problem.
OK , so here is my problem. My iPhone 2G was running 3.1.2 the last 12-3 months but today I was stupid enough to update to 3.1.3 as the final version. So now when I go to wi-fi I switch it on it does not see any wi-fi connections. The only way to see
-
Importing a cassette tape into I tunes
Can I import and save a cassette tape into itunes thanks