Procedure fails to create executing from Urban Code Deploy - sql

I've run into problems with following script which I'm trying to execute. In SQLDeveloper or other tools like DataGrip, everything works fine, so in my understanding, this is UCD issue.
...more inserts
insert into M_MIGRATION_CONTROL values ('PRODUCTREL', 'M_' || 'PRODUCTREL');
CREATE OR REPLACE PROCEDURE MIGRATE_DATA_BEFORE_DEPLOY IS
TABLE_NAME VARCHAR2(128);
MIGRATION_TABLE_NAME VARCHAR2(128);
CURSOR MIGRATION_CURSOR IS SELECT * FROM M_MIGRATION_CONTROL;
BEGIN
OPEN MIGRATION_CURSOR;
LOOP
FETCH MIGRATION_CURSOR INTO TABLE_NAME, MIGRATION_TABLE_NAME;
EXIT WHEN MIGRATION_CURSOR%NOTFOUND;
EXECUTE IMMEDIATE 'CREATE TABLE '||MIGRATION_TABLE_NAME||' AS SELECT * FROM '||TABLE_NAME||'';
END LOOP;
CLOSE MIGRATION_CURSOR;
END MIGRATE_DATA_BEFORE_DEPLOY;
/
insert into A_ACCEPTEDINCOMETYPEOPTION select * from M_A_ACCEPTEDINCOMETYPEOPTION;
insert into A_INSTALMENT select * from M_A_INSTALMENT;
...more inserts
with errors:
[sql] Failed to execute: MIGRATION_TABLE_NAME VARCHAR2(128)
[sql] java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
[sql] Failed to execute: CURSOR MIGRATION_CURSOR IS SELECT * FROM M_MIGRATION_CONTROL
When I print procedure body from Oracle i get:
PROCEDURE MIGRATE_DATA_BEFORE_DEPLOY IS TABLE_NAME VARCHAR2(128)
So I think that client ends create procedure after first ;
Can you help me/advise me, how should this script look like for correct execution?
(Oracle 12.1)

You are using SQL-JDBC plugin for Urban Code Deploy.
According to their documentation/troubleshooting:
The SQL-JDBC plugin does not support deploying stored procedures.
There is a separate SQL*Plus plugin which you may be able to use instead.

Related

PL/SQL Developer - Creating dynamic SQL

I'm using PL/SQL Developer. I'm trying to get query results to excel via vba. Since query is so long, i decided to create table with the query results and then simply get the table results with vba. In order to create table via excel i needed to create procedure with dynamic sql. So this is what i tried so far (even this simple example doesn't work):
create or replace procedure d_x IS
str VARCHAR(81) = 'create table as select 1 as x from dual'
BEGIN
EXECUTE IMMEDIATE str;
END;
Procedure completes without error. But when i try to execute it to create table it throws an error.
Execute statement:
EXECUTE d_x;
The execute statement throws 'ORA-00900' Invalid sql statement error.
I'm kinda new to pl sql so i couldn't find a solution to this.
Any help would be appreciated, thanks.
Procedure you posted can't possibly execute without errors because it is invalid. When fixed, looks like this:
SQL> create or replace procedure d_x IS
2 str VARCHAR(81) := 'create table test as select 1 as x from dual';
3 BEGIN
4 EXECUTE IMMEDIATE str;
5 END;
6 /
Procedure created.
In tools that support execute, you can run it as:
SQL> execute d_x
PL/SQL procedure successfully completed.
SQL> select * from test;
X
----------
1
"Correct" way - which works anywhere - is to enclose it (the procedure) into begin-end block:
SQL> drop table test;
Table dropped.
SQL> begin
2 d_x;
3 end;
4 /
PL/SQL procedure successfully completed.
SQL>
I suggest you do that.
In PL/SQL Developer you can click on the procedure name and choose 'Test', which will generate a calling script as a Test window.
You can only use execute in a Command window, because it's a SQL*Plus command and not part of SQL or PL/SQL, and the Command window is a SQL*Plus emulator.
In a SQL window you could either use a complete PL/SQL block:
begin
d_x;
end
/
or use the SQL call command:
call d_x();
Note that call() requires brackets regardless of whether or not the procedure has any parameters.
The / character is useful as a separator when using PLSQL blocks in a SQL window where you have more than one statement, otherwise PL/SQ Developer won't know where one ends and the next starts.
A Test window can only have one statement and only a single PL/SQL block or SQL statement is allowed, so there is no / character at the end.

Oracle: Setting Session Parameters in Packages and Procedures

I'm a SQL Server DBA currently getting up to speed on Oracle. I'm trying to create something very similar to sp_WhoIsActive for SQL Server but for Oracle without reinventing the wheel. Essentially all I'm doing is selecting some values from v$session and inserting them into a table (poor man's ASH/AWR).
It would seem that in Oracle 12.1, there's a bug when querying dictionary views where it can take forever due to bad parsing logic (Bug 22225899 : SLOW PARSE FOR COMPLEX QUERY). The work-around is to set a session parameter:
alter session set "_optimizer_squ_bottomup"=false;
In T-SQL, I could very easily execute a stored procedure in-session and set this variable at runtime. However in Oracle, it wouldn't seem thats the case.
Sample Code:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(
v_temp NUMBER :=1
) IS
BEGIN
alter session set "_optimizer_squ_bottomup"=false;
INSERT INTO SY_DB_ACTIVITY
SELECT
<fields>
FROM
v$session;
commit;
When I run this, I get the error:
"PLS-00103: Encountered symbol 'ALTER' when expecting one of the following..."
Right now, the only way I know how to do this is via a utility like SQL Plus that initiates an interactive user session. Can anyone give me some direction as to how Oracle handles this situation? I'd like to bundle this up into a SP or a Package and then call it from Oracle Scheduler.
Hre is a simple example how to execute alter session inside of the procedure:
CREATE PROCEDURE SP_DB_ACTIVITY IS
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
END;
/
Here is the way you can combine that with your select and insert statement:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(v_temp IN number) AS
v_Id NUMBER;
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
SELECT 1
INTO v_Id
FROM dual;
INSERT INTO SY_DB_ACTIVITY (id) VALUES(v_Id);
END SP_DB_ACTIVITY;
/
Here is a small DEMO where you can see what will procedure do when you call it and how you can call it. Also, in this example you are calling procedure with and IN parameter. So you can use that parameter for something and in the example above is the procedure without any parameters...
You can also, of course, insert into table directly:
CREATE OR REPLACE PROCEDURE SP_DB_ACTIVITY
(v_temp IN number) AS
v_Id NUMBER;
BEGIN
EXECUTE IMMEDIATE 'alter session set "_optimizer_squ_bottomup"=false';
INSERT INTO SY_DB_ACTIVITY(id)
select 1
from dual;
END SP_DB_ACTIVITY;
/

PLSQL statement executes but not getting output

I have this procedure to create a table 'circle' and insert some radius and corresponding area to it, this is my code
create or replace procedure table1
is
BEGIN
execute immediate'drop table circle';
execute immediate'create table circle (r int, a int)';
end;
declare
r int;
ar float;
begin
for r in 3 .. 7 loop
ar:=3.14*r*r;
INSERT INTO circle VALUES(r,ar);
end loop;
execute immediate 'select * from circle';
end;
But when I run this I get this warning
Warning: Procedure created with compilation errors.
and when I try to find the table I get
SQL> select * from circle;
select * from circle
*
ERROR at line 1:
ORA-00942: table or view does not exist
what is wrong in my code?
In the code mentioned above, you're just creating a procedure. It also needs to be executed successfully before using the table in anonymous block.
I've created your procedure here and the procedure is created successfully.
Just when you try to execute it, handle the exception for when the table circle doesn't exist in your procedure's code and then execute (or call) it. Further, you could use the anonymous block to insert the values in your table.
If the table doesn't exist, attempting to drop it will fail. The rest of the code won't run, so your table is never created
Carry out your drop attempt and catch the error, then proceed
This answer has more info: Oracle: If Table Exists

Wrong number or types of arguments

Create or replace procedure sp_create_tables as
Lv_str varchar2(1000);
Begin
For I in (select distinct(deptno) from emp) loop
Lv_str:='create table deptno'||I||' select * from emp where
1=2';
Execute immediate lv_str;
End loop;
End;
From what I can understand, your question is probably "why the procedure throws this compilation error"
PLS-00306: wrong number or types of arguments in call to '||'
The reason is that the implicit cursor loop variable I refers to the set of records from the query and not the deptno itself. In order to refer to the deptno, you should use <loop_variable>.deptno. Also 2 other things you should change: The as keyword is missing and DISTINCT is a keyword and you are using it as a function, which works because of default parentheses, but is not the right way to use it.
Create or replace procedure sp_create_tables as
Lv_str varchar2(1000);
Begin
For I in (select distinct dept from emp) loop
Lv_str:='create table deptno'||I.deptno||' as select * from emp where
1=2';
Execute immediate lv_str;
End loop;
End;
In this line of code I is an implicit rowtype variable, with a data structure defined by the projection of the driving select statement:
For I in (select distinct(deptno) from emp) loop
But you are attempting to reference it in your dynamic SQL as though it were an attribute. You need to use a column name instead.
Create or replace procedure sp_create_tables as
Lv_str varchar2(1000);
Begin
For I in (select distinct (deptno) from emp) loop
Lv_str:='create table deptno'|| I.deptno ||
' as select * from emp where 1=2';
Execute immediate lv_str;
End loop;
End;
Incidentally there is a bug in your dynamic SQL statement. The correct syntax is CREATE TABLE ... AS SELECT .... Dynamic SQL is hard because the compiler can't validate the bits of code in strings. Consequently what should be compilation errors manifest themselves as runtime errors. You will find it helpful to instrument your code with some logging (or dbms_output.put_line()) to record the assembled statement before it runs. It makes debugging a lot easier.
" i have got a error saying -01031 insufficient priviliges"
So what this means is your authorisation to create a table was granted through a role. The Oracle security model does not allow us to build PL/SQL programs - or views - using privileges granted through a role. This includes PL/SQL executing DDL through dynamic SQL. You need a DBA user to grant CREATE TABLE to your user directly.

How to execute stored procedures containing dynamic SQL in oracle?

I've created the following procedure
Create or replace procedure abcd
(
tab_name in USER_TABLES.table_name%type
)
is
begin
execute immediate
'select * from'||tab_name;
end abcd;
The procedure gets compiled.
I am trying to get the output using the following
select abcd('Table') from dual ;
I am new to dynamic SQL and this does not seem to work for me. I keep getting the error
[Error] Execution (44: 8): ORA-00904: "ABCD": invalid identifier
Can someone please help ?
Regards,
Kshitij
You're missing a space before your table name:
create or replace procedure abcd (tab_name in USER_TABLES.table_name%type )
is
begin
execute immediate 'select * from '||tab_name;
end abcd;
This won't work because you're trying to call it as a function, not a procedure:
select abcd('Table') from dual ;
Your second attempt should now work:
exec abcd('Table');
... but will now get a different error. In PL/SQL you have to select into something. In this case you probably want to open a cursor with the dynamic string and do something with the results. Not really sure what your end goal is though.
You should also read up about SQL injection while you learn about dynamic SQL.
you cannot perform a select on a procedure, a function will work only if single record return.
use
begin
abcd();
end;
or use
execute keyword
ALSO use a space after from in query
It will not work.
When you invoke EXECUTE IMMEDIATE the sql statement is send to SQL engine. No results are passed back to the PL/SQL.
Writing "SELECT * FROM a_table" is not that hard and much safer.