If I am querying below query, getting error - oracle

Exec('select * from dual ' );
Showing invalid Sql query. Is it a valid query? If no, what could the reason and solution?

EXEC is a SQL*Plus command, used to run PL/SQL code (usually procedures).
But, if you insist on selecting from dual, no problem. Here's how: as it has to be PL/SQL, declare a variable and select into it. As DUAL has one column (named DUMMY), it'll work just fine:
SQL> var l_dum varchar2;
SQL> exec select * into :l_dum from dual;
PL/SQL procedure successfully completed.
SQL> print l_dum
L_DUM
--------------------------------
X
SQL>
What we normally do is
SQL> select * from dual;
D
-
X
SQL>
Your error? Single quotes, no variable to select into.

EXEC[UTE] IMMEDIATE must be used within an anonymous block or procedure.
For example:
Begin
Execute Immediate 'Select * From Dual';
End;
Here is a simple Youtube explanation:
https://youtu.be/47KzYVBNbIs

Related

How to create an alias from an select result in oracle?

I want to create an alias from an select result.I've tried to use oracle dynamic query but doesn't working.Here is my sql:
declare
v_a varchar2(50);
sql_smt varchar2(200);
begin
select TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd')) INTO v_a from dual;
sql_smt :='SELECT sysdate as :1 FROM dual';
execute immediate sql_smt using v_a;
end;
I want to reach to an result like in the photo.
Thanks for any help!
As you've tagged this for SQL Developer you could use (ab)use substitution variables for this; in your worksheet do:
column x_title new_value y_title noprint;
select TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd'))
as x_title
from dual;
set verify off
select sysdate as "&y_title" from dual;
which when you run as a script (F5) produces this in the Script Output window:
<blank lines ...>
#20190126-
----------
2019-02-25
and then if you run the last line again as a statement (control-enter) the Query Result window shows it as you wanted, from the image in your question.
You could also use the column command which makes the output in the Script Output closer to what you wanted when run as a script:
column sysdate heading &y_title
select sysdate from dual;
#20190126-20190227
------------------
2019-02-25
but then when run as a statement the Query Results window doesn't honour that heading.
Note that this is all client-specific functionality, not SQL - it will work in SQL Developer, and the script versions will work in SQL*Plus and SQLcl, but not in other clients (unless they have tried to feature-match SQL*Plus to some extent).
If you aren't only going to be viewing the results in one of those clients but actually want to end up, say, pulling them into an application over JDBC or whatever, then other solutions would be more appropriate. Generating a ref cursor with the column as the name you want would be fairly simple. But that's not what you've asked for...
OK, since you asked in a comment, you can open a ref cursor in an anonymous block:
var rc refcursor
declare
l_alias varchar2(50);
begin
select TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd'))
into l_alias
from dual;
open :rc for 'SELECT sysdate as "' || l_alias || '" FROM dual';
end;
/
PL/SQL procedure successfully completed.
print rc
#20190127-
----------
2019-02-26
or without the local variable:
var rc refcursor
begin
open :rc for 'SELECT sysdate as "'
|| TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd'))
|| '" FROM dual';
end;
/
PL/SQL procedure successfully completed.
print rc;
#20190127-
----------
2019-02-26
Again var[iable] and print are client-specific commands; and I don't think there's a way to get the results in the Query Results grid with this approach. But you can use the same anonymous block approach from other clients or applications; e.g. from JDBC you could have a statement as:
String sql = "begin open ? for 'SELECT sysdate as \"'"
+ "|| TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd'))"
+ "|| '\" FROM dual'; end;";
and then bind the ? parameter placeholder as a cursor type before executing. That probably isn't very useful though as you'd have to examine the metadata to find the column alias anyway, and you could generate it on the application side using the application language tools (e..g Java date manipulation).
You could also create a function that returns a ref cursor, which you could then call from a plain query (instead of an anonymous block), which would allow you to see it in the Query Results grid - possibly with an extra step to show the cursor result. But you made not need that extra level of code or want another object to be created in your DB.
Would something like this work?
declare
col_hdr varchar2(50);
sys_date varchar2(26);
sql_smt varchar2(200);
begin
select TO_CHAR('#'||TO_CHAR(sysdate-30,'yyyymmdd')||'-'||TO_CHAR(sysdate+2,'yyyymmdd')) INTO col_hdr from dual;
sql_smt :='SELECT sysdate ' || ' as "' || col_hdr || '" FROM dual';
dbms_output.put_line(sql_smt);
execute immediate sql_smt into sys_date;
dbms_output.put_line('done');
end;

PL/SQL set a link as default at the begining of the script

I need to select a link at the beginning in the script. Usually we do select links as below,
begin
select * from v$database#linkname;
end;
But now I need to select the link at the beginning something like this,
begin
select_link 'linkname';
select * from v$database;
end;
Thank you!
select * from v$database#linkname;
You cannot simply have a SELECT statement like that in PL/SQL. It expects an INTO clause.
If I understand correct;y, you want to parameterize the DATABASE LINK. I am afraid you need to (ab) use dynamic SQL.
For example,
SQL> var cur refcursor
SQL> DECLARE
2 var_link varchar2(20);
3 BEGIN
4 var_link:='#your_db_link';
5 OPEN :cur FOR 'SELECT * FROM dual'||var_link;
6 END;
7 /
PL/SQL procedure successfully completed.
SQL> print cur
D
-
X
SQL>

simple way to return 2 or more rows using a SELECT in pl/sql

I am trying to figure out the most simple way to return 2 or more rows using a select statement in pl/sql to the sqlplus output. Here is a basic example.
begin
select sysdate,'12345' xid from dual
union all
select sysdate,'67890' xid from dual;
end;
/
Error is "an INTO clause is expected in this SELECT statement"
You would use a cursor to return the result of a query:
SQL> VARIABLE x REFCURSOR
SQL> BEGIN
2 OPEN :x FOR SELECT ROWNUM FROM dual CONNECT BY LEVEL <= 3;
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> PRINT x
ROWNUM
----------
1
2
3
Yes, you can return a ResultSet from a PL/SQL. Take a look at this URL.
When writing a SQL code in a BEGIN-END block, you cannot display its result-set in the editor. Trim the BEGIN-END from your query, and it would happily display the results.
Basically, code within a BEGIN-END block is not used for displaying results, it is used for data processing instead. So you should simply write:
SELECT SYSDATE,'12345' XID FROM DUAL
UNION ALL
SELECT SYSDATE,'67890' FROM DUAL;
to display the result-set in your SQL editor.
Also notice that I removed alias "XID" in second SELECT statement: you need to give column aliases in only first query in a UNION/UNION ALL statement.

How to calculate value of string in oracle?

If I have a string say "3*2+24" how can calculate its value in Oracle? In sql server you can do exec ('select 3*2+24') and it returns 30
Thanks
Here's a little function to calculate arbitrary strings of arithmetic:
SQL> CREATE OR REPLACE FUNCTION calc(pi_val VARCHAR2) RETURN NUMBER IS
2 v_return NUMBER;
3 BEGIN
4 EXECUTE IMMEDIATE 'select '||pi_val||' from dual' INTO v_return;
5 RETURN v_return;
6 END;
7 /
Function created
SQL> SELECT calc('2*6*10') FROM dual;
CALC('2*6*10')
--------------
120
SQL>
Obviously, for production purposes you'd need some error handling...
You can use DCookie's solution.
You can decrease the possibility of an sql injection attack by creating a new user without privileges.
Log in as system and create a new user without privileges:
create user new_user identified by password_new_user;
Create the function (as system) in schema new_user.
create or replace function new_user.calc(pi_val varchar2) return number
is
v_return number;
begin
execute immediate 'select '||pi_val||' from dual' INTO v_return;
return v_return;
end;
/
Next grant execute privileges (as system) on function new_user.calc to the relevant Oracle users (for instance tuinstoel (that's me)).
grant execute on new_user.calc to tuinstoel;
Log in as user tuinstoel.
connect tuinstoel/cheese_and_cheese#ora11
SQL> select new_user.calc('2+3') from dual;
NEW_USER.CALC('2+3')
--------------------
5
Everyone who calls the function new_user.calc has the privileges of new_user (none) inside function new_user.calc, not the rights of the caller (definer's privileges not invoker's privileges).
When you don't want to include new_user. in every call to calc do as tuinstoel:
create synonym calc for new_user.calc;
Next you can test this with:
SQL> select calc('2+3') from dual;
CALC('2+3')
-----------
5
edit1: Others have contemplated about this solution and they have pointed out some (potential) problems: See http://forums.oracle.com/forums/thread.jspa?forumID=75&threadID=943576 .
In ORACLE you can do any computation you want using the dual feature. For example
SELECT 3*3-(2+2) FROM DUAL
However, you cannot do
SELECT '3*3-(2+2)' FROM DUAL
Because it will just return the string of '3*3-(2+2)'. If all you have is a string, I would probably strip it out into a numeric function then do the calculation.
You can use the xmlquery() function to implement it. Here is a sample code:
select
xmlquery(
replace( 'your variable', '/', ' div ')
returning content
).getNumberVal()
from
dual;
For example the code below
SELECT
XMLQUERY(
REPLACE( '3/4', '/', ' div ')
RETURNING CONTENT
).getNumberVal() FROM DUAL;
returns 0.75
It's a bit clunkier in Oracle but it can be done.
SQL> set serveroutput on
SQL> declare
2 str varchar2(250) := '3*2+24';
3 n number;
4 begin
5 execute immediate 'select '||str||' from dual' into n;
6 dbms_output.put_line(str||' = '||to_char(n)||' !!');
7 end;
8 /
3*2+24 = 30 !!
PL/SQL procedure successfully completed.
SQL>

How to return a resultset / cursor from a Oracle PL/SQL anonymous block that executes Dynamic SQL?

I have this table:
ALLITEMS
---------------
ItemId | Areas
---------------
1 | EAST
2 | EAST
3 | SOUTH
4 | WEST
The DDL:
drop table allitems;
Create Table Allitems(ItemId Int,areas Varchar2(20));
Insert Into Allitems(Itemid,Areas) Values(1,'east');
Insert Into Allitems(ItemId,areas) Values(2,'east');
insert into allitems(ItemId,areas) values(3,'south');
insert into allitems(ItemId,areas) values(4,'east');
In MSSQL, to get a cursor from a dynamic SQL I can do:
DECLARE #v_sqlStatement VARCHAR(2000);
SET #v_Sqlstatement = 'SELECT * FROM ALLITEMS';
EXEC (#v_sqlStatement); --returns a resultset/cursor, just like calling SELECT
In Oracle, I need to use a PL/SQL Block:
SET AUTOPRINT ON;
DECLARE
V_Sqlstatement Varchar2(2000);
outputData SYS_REFCURSOR;
BEGIN
V_Sqlstatement := 'SELECT * FROM ALLITEMS';
OPEN outputData for v_Sqlstatement;
End;
--result is : anonymous block completed
**But all I get is
anonymous block completed".
How do I get it to return the cursor?
(I know that if I do AUTOPRINT, it will print out the information in the REFCURSOR (it's not printing in the code above, but thats another problem))
I will be calling this Dynamic SQL from code (ODBC,C++), and I need it to return a cursor. How?
You can write a PL/SQL function to return that cursor (or you could put that function in a package if you have more code related to this):
CREATE OR REPLACE FUNCTION get_allitems
RETURN SYS_REFCURSOR
AS
my_cursor SYS_REFCURSOR;
BEGIN
OPEN my_cursor FOR SELECT * FROM allitems;
RETURN my_cursor;
END get_allitems;
This will return the cursor.
Make sure not to put your SELECT-String into quotes in PL/SQL when possible. Putting it in strings means that it can not be checked at compile time, and that it has to be parsed whenever you use it.
If you really need to use dynamic SQL you can put your query in single quotes:
OPEN my_cursor FOR 'SELECT * FROM allitems';
This string has to be parsed whenever the function is called, which will usually be slower and hides errors in your query until runtime.
Make sure to use bind-variables where possible to avoid hard parses:
OPEN my_cursor FOR 'SELECT * FROM allitems WHERE id = :id' USING my_id;
in SQL*Plus you could also use a REFCURSOR variable:
SQL> VARIABLE x REFCURSOR
SQL> DECLARE
2 V_Sqlstatement Varchar2(2000);
3 BEGIN
4 V_Sqlstatement := 'SELECT * FROM DUAL';
5 OPEN :x for v_Sqlstatement;
6 End;
7 /
ProcÚdure PL/SQL terminÚe avec succÞs.
SQL> print x;
D
-
X
You should be able to declare a cursor to be a bind variable (called parameters in other DBMS')
like Vincent wrote, you can do something like this:
begin
open :yourCursor
for 'SELECT "'|| :someField ||'" from yourTable where x = :y'
using :someFilterValue;
end;
You'd have to bind 3 vars to that script. An input string for "someField", a value for "someFilterValue" and an cursor for "yourCursor" which has to be declared as output var.
Unfortunately, I have no idea how you'd do that from C++. (One could say fortunately for me, though. ;-) )
Depending on which access library you use, it might be a royal pain or straight forward.
This setting needs to be set:
SET SERVEROUTPUT ON

Resources