UNION on dynamic SQL statements - oracle

What I am trying to accomplish is essentially this:
SELECT 1 FROM DUAL
UNION
EXECUTE IMMEDIATE 'SELECT 2 FROM dual';
I am actually a penetration tester trying to bypass a web application firewall, so I am sure this looks silly/strange from the other side. Basically, I need to be able to do a UNION with dynamic queries in order to bypass a filter. So, in this example, you are passing a string from Java into an Oracle DB using this function.
I don't have any feedback from the database on what is wrong with my query, and could not find any documentation for someone doing something similar. I need a simple example where I UNION a normal query with a simple dynamic SQL string.

The execute immediate statement is only valid inside a PL/SQL block. You can't mix it with plain SQL. You can run (only) PL/SQL dynamically too, but again not mixing the two in one statement like you've tried.
If you run what you showed in a normal client you'd see it complains:
Error starting at line : 1 in command -
SELECT 1 FROM DUAL
UNION
EXECUTE IMMEDIATE 'SELECT 2 FROM dual'
Error at Command Line : 3 Column : 1
Error report -
SQL Error: ORA-00928: missing SELECT keyword
00928. 00000 - "missing SELECT keyword"
*Cause:
*Action:
Even if the statement you pass is itself executed dynamically, you'd see the same error:
BEGIN
EXECUTE IMMEDIATE q'[SELECT 1 FROM DUAL
UNION
EXECUTE IMMEDIATE 'SELECT 2 FROM dual']';
END;
/
Error report -
ORA-00928: missing SELECT keyword
ORA-06512: at line 2
00928. 00000 - "missing SELECT keyword"
A further consideration, though it's a bit moot here, is that a dynamic query isn't actually executed if you aren't consuming the results by selecting into a variable (see the note here.

Related

Why does this db link chain cause a "looping chain of synonyms" error only within an anonymous block?

I am in a position which requires I pull data to my primary database through a daisy chained dblink set up similar to what is described in this answer
DBLINK_SERVER2 -> SYNONYM -> DBLINK_SERVER3
The synonym is set up on server 2 like this:
CREATE OR REPLACE SYNONYM "MY_USER"."THE_VIEW" FOR "THE_VIEW"#"DBLINK_SERVER3"
When I run a simple select statement from server 1, it works fine and pulls back exactly what i'd expect from server 3's view:
SELECT COUNT(*) FROM THE_VIEW#DBLINK_SERVER2;
However, whenever I try to run code in an anonymous block any reference to the dblink will cause a "looping chain of synonyms" error.
DECLARE
testnum VARCHAR2(50);
BEGIN
SELECT COUNT(*) INTO testnum FROM THE_VIEW#DBLINK_SERVER2;
END;
/
Error report -
ORA-06550: line 2, column 22:
PL/SQL: ORA-01775: looping chain of synonyms
ORA-06550: line 2, column 1:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
There aren't any synonyms on server 1 that i can see which reference the view or dblink. If i run this same test on server 2 both the simple command and block work fine when i use the synonym. Any idea why the block fails on server 1 but not if i run the same thing outside of the block? Is this some kind of permissions problem?
*** Edit ***
We never determined what was causing this, but the DBA changed it so that we were referencing a view in server 2 instead of a symlink. That resolved our problem.
CREATE VIEW THE_VIEW AS SELECT * FROM THE_VEW#DBLINK_SERVER3

Oracle basic multi-statement block

In SQL Server, multiple statements in SSMS can be performed. In Oracle (using toad), I don't know why I receive certain errors doing the same thing. For example, I assume an Oracle requirement is to place them in a block, but I still get the following:
DECLARE
v_datetime TIMESTAMP := SYSDATE;
BEGIN
insert into sometable_log values (v_datetime, 'this is a test ',1);
select * from sometable_log where event_dt = v_datetime;
END;
produces:
[Error] Execution (5: 1): ORA-06550: line 4, column 1: PLS-00428: an
INTO clause is expected in this SELECT statement
Why would I need to use an into clause? Can someone please help me understand what this is?
Thank you!
When executing the block of code, Oracle expects that the select command should have some code-like effect. That's why it wants you to add the into clause.
To do what you need, just move the select statement outside of the PL/SQL begin/end block.

Is SQL statement in EXECUTE IMMEDIATE parsed at run time?

Considering below procedure. For processing, it has to go through all the processing phases anyway. So my question is: Is it at this parse phase 'Select job_id from asfd' still treated as string and while the execution phase of EXECUTE IMMEDIATE the statement 'Select job_id from asfd' is parsed again now as SQL statement?
CREATE OR REPLACE PROCEDURE test_ei
IS
BEGIN
EXECUTE IMMEDIATE ‘select job_id from asfd’; //line 3
END;
One explanation I found in here is the asdf table does not exist but gut successfully compiled, so 'Select job_id from asfd' is still treated as string at this stage. Any corrections please.
As matter of fact even when EXECUTE IMMEDIATE 'select * asfd'; is replace in line 3 it still complies successfully. So I guess above explanation is correct.
Yes. At EXECUTE IMMEDIATE, the runtime engine must first parse the statement.And i.e the reason why you cannot bind in the names of schema elements (tables, columns, etc.)
More details:
The parse phase is what guarantees that the SQL statement is properly defined. PL/SQL can tell that the following statement is valid without having to know the value of :xyz.
'UPDATE emp SET sal = :xyz'
But how can PL/SQL know if the following statement is well formed? We can't, and so the restriction.
'UPDATE emp SET :col_name = :xyz'

Running PL/SQL script in PHP

I have a script in PL/SQL , that drop some tables , sequences , triggers, and creating them again in the same script , I need this script in my website for deleting all data from database (and I want to acces this script pressing one button on website) so I tried to do a function / procedure in PL/SQL that read line by line from the script file and executing every line with dynamic sql , everything went ok till one error at:
CREATE OR REPLACE TRIGGER players_bir BEFORE INSERT ON players FOR EACH ROW BEGIN SELECT players_seq.NEXTVAL INTO :new.id FROM dual END
this gave me the error:
ORA-24344: success with compilation error
I searched for solutions, but I didn't find anything.
You are missing the semi-colon after dual on your SELECT statement. This ORA error generally means you compiled some code, but that is has some issue.
CREATE OR REPLACE TRIGGER players_bir
BEFORE INSERT ON players
FOR EACH ROW
BEGIN
SELECT players_seq.nextval
INTO :new.id
FROM dual;
END
Looking in all_errors will show you what the issue is or you could manually compile this trigger in some IDE (like SQL Developer) and that should also make it obvious.
SELECT *
FROM all_errors e
WHERE e.name = 'PLAYERS_BIR'
AND e.type = 'TRIGGER';
Additionally if all you are using your trigger for is to set some identity column and you are on Oracle 12c you can use some of the new features to accomplish this. Triggers are inherently slow and the new identity feature performs about as good as referencing the sequence directly in your INSERT.

How can I avoid errors with dbms_metadata.GET_DEPENDENT_DDL

I'm writing a custom program to dump the database metadata to files in order to manage them with version control. The default way that data pump or export works isn't ideal for a few reasons (eg. I'd like a separate directory per table).
Sql Developer provides a number of ways of creating export scripts for any object. One way is just by right-clicking the object and selecting Quick DDL. By viewing the logs it creates, one can see the actual SQL it issues to create the DDL script. I've used these scripts to write my custom program and for the most part, they've been perfect.
When I generate the DDL for a materialized view, the SQL it generates is:
SELECT DBMS_METADATA.GET_DDL('MATERIALIZED_VIEW',:name,:owner) FROM DUAL
UNION ALL
SELECT DBMS_METADATA.GET_DEPENDENT_DDL('INDEX',TABLE_NAME, TABLE_OWNER) FROM (
SELECT table_name, table_owner FROM all_indexes
WHERE table_owner = :owner AND table_name = :name
AND index_name NOT IN (
SELECT constraint_name FROM sys.all_constraints
WHERE table_name = table_name AND constraint_type = 'P'
) AND ROWNUM = 1
)
UNION ALL
SELECT dbms_metadata.GET_DEPENDENT_DDL ('COMMENT', :name,:owner ) FROM DUAL
For this script, when executed via SQL Developer Quick DDL, it generates the metadata for the materialized view properly. When I run this script in a program (or even manually with SQL Developer itself), it produces the following errors:
ORA-31608: specified object of type COMMENT not found
ORA-06512: at "SYS.DBMS_METADATA", line 5805
ORA-06512: at "SYS.DBMS_METADATA", line 8436
ORA-06512: at line 1
31608. 00000 - "specified object of type %s not found"
*Cause: The specified object was not found in the database.
*Action: Correct the object specification and try the call again.
This particular materialized view doesn't have any comments (obviously), but I would have expected this part of the clause to just return 0 rows instead of generating an error (especially since SQL Developer uses this itself seemingly without errors).
Is there a way I can avoid this error, while still including comments in the metadata if they exist?
This issue exists on both Oracle 10g & 11g databases.
I was not able to test as I don't really know how to create mview without comment... However the below should work for you. Try to query dba_mview_comments instead of dual to not execute the function when you don't have comments.
UNION ALL
SELECT dbms_metadata.get_dependent_ddl ('COMMENT', :name, :owner)
FROM dba_mview_comments mvc
WHERE mvc.mview_name = :name AND
mvc.owner = :owner AND
length(comments) > 0 AND
rownum = 1

Resources