How to use a variable in a LIKE clause in PL/SQL - oracle

I am new to Oracle and learning; I am simply trying to run this T-SQL query
DECLARE #SearchObj varchar(100);
SET #SearchObj='%aldbrough%';
SELECT
obj_id,
name,
description
FROM
agnis.t_object
WHERE
lower(name) = ObjToSearch ;
I am using SQL Developer Oracle tool which also have a "Scratch Editor" to help with translation from T-SQL. When i run the tool it gave me this code
DECLARE
v_SearchObj VARCHAR2(100);
BEGIN
v_SearchObj := '%aldbrough%' ;
SELECT obj_id ,
NAME ,
DESCRIPTION
FROM agnis.t_object
WHERE LOWER(NAME) = ObjToSearch;
END;
but the same tool give me this error
Error report -
ORA-06550: line 10, column 26:
PL/SQL: ORA-00904: "OBJTOSEARCH": invalid identifier
ORA-06550: line 6, column 4:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
so what is the correct syntax to use a variable into a LIKE clause that returns multiple rows?
I hope I do not have to use cursors etc for such of a simple statement as suggested in this question

Well, yes - those "translators" don't always do what they are supposed to.
This is how your code should look like:
use like, not = in the where clause
in PL/SQL, you have to put the result of the select statement into something - for example, locally declared variables (as my example shows).
So:
DECLARE
v_SearchObj VARCHAR2 (100) := '%aldbrough%';
--
v_obj_id t_object.obj_id%TYPE;
v_name t_object.name%TYPE;
v_description t_object.description%TYPE;
BEGIN
SELECT obj_id, NAME, DESCRIPTION
INTO v_obj_id, v_name, v_description
FROM agnis.t_object
WHERE LOWER (NAME) LIKE v_searchobj;
END;
If such a code returns an error - too_many_rows (and yes, it does), then one option is to loop through rows and do something (such as display those values):
DECLARE
v_SearchObj VARCHAR2 (100) := '%aldbrough%';
BEGIN
FOR cur_r IN (SELECT obj_id, NAME, DESCRIPTION
FROM agnis.t_object
WHERE LOWER (NAME) LIKE v_searchobj)
LOOP
DBMS_OUTPUT.put_line (
'Name = ' || cur_r.name || ', description = ' || cur_r.description);
END LOOP;
END;

Since this is tagged SQL Developer, use a bind variable:
SELECT obj_id,
name,
description
FROM agnis.t_object
WHERE lower(name) = :ObjToSearch;
and SQL developer will pop up a dialog box where you can set the value of the ObjToSearch variable.
If you want to specify the bind variable in code then:
VARIABLE objtosearch VARCHAR2(50)
BEGIN
:objtosearch := '%aldbrough%';
END;
/
SELECT obj_id,
name,
description
FROM agnis.t_object
WHERE lower(name) = :ObjToSearch;
And run the statements as a script using F5 rather than as individual statements.

Related

ORACLE select into variable

This should be easy as answers from here and here are suggesting. But, I am receiving an error:
ORA-00905: missing keyword
00905. 00000 - "missing keyword"
*Cause:
*Action: Error at Line: 7 Column: 36
My code:
vEXTERNAL_ACCOUNT_ID VARCHAR2(20);
(SELECT EXTERNAL_ACCOUNT_ID INTO vEXTERNAL_ACCOUNT_ID FROM TOF_ORDER_DATA WHERE ID =
(SELECT TOF_ORDER_DATA_ID FROM TOF_WFI WHERE WFI_ID = 3466444));
All I want is to set vEXTERNAL_ACCOUNT_ID from query above (it returns only one result). I don't understand what am I doing wrong here?
This is PL/SQL, so:
declare
vexternal_account_id varchar2(20);
begin
select external_account_id
into vexternal_account_id
from tof_order_data
where id = (select tof_order_data_id
from tof_wfi
where wfi_id = 3466444
);
dbms_output.put_line('Value = ' || vexternal_account_id);
end;
declare the variable
use begin-end keywords
remove outmost brackets
in order to display value returned by query, use dbms_output.put_line
don't forget to set serveroutput on in tool you use!

Oracle PL/SQL SELECT INTO clause thinks it needs another INTO

I have a simple test function where I'm passing in a specific ID (the primary key of the table I'm selecting from), and computing a simple function on it and the parameters.
The skeleton code and test:
create or replace function test(id varchar2, area float) return float is
theRow forest%ROWTYPE;
begin
select * into theRow from forest where Forest_No = id;
return area / theRow.Area;
end;
begin
select test('1', 16000) from dual;
end;
The output:
[2019-10-14 21:19:10] [65000][6550] ORA-06550: line 2, column 5:
[2019-10-14 21:19:10] PLS-00428: an INTO clause is expected in this SELECT statement
I am at a loss for what to do here, as far as I can tell the documentation and examples use the same order and syntax. I have tried moving the into clause to the end as in Postgresql, but that did not work.
What have I missed here?
Issue is in calling statement.
Whenever select statement is used in plsql block it must have into clause to assign return value to variable.
You should remove begin and end from your calling code:
--begin -- remove this
select test('1', 16000) from dual;
--end; -- remove this
Or if you want to use it in plsql block then add into clause:
Declare
Area_ float(precision);
begin
select test('1', 16000) into area_ from dual;
-- use area_ in your code wherever required
dbms_output.put_line('area: ' || area_);
end;
Cheers!!

Store Procedure hit SQL Statement Ignored

create or replace PROCEDURE GEN_STATEMENT_SP(indexNM IN VARCHAR2, tableNM IN VARCHAR2) AS
BEGIN
DECLARE
uniqueSTMT VARCHAR2(30);
nonUniqueSTMT VARCHAR2(30);
charOn VARCHAR2(5);
tempfld VARCHAR2(500) ;
CURSOR chkTyp IS(SELECT ES_UNIQUENESS from sys.dba_ind_columns where INDEX_NAME = indexNM and TABLE_NAME = tableNM);
CURSOR tblColumn IS(SELECT INDEX_NAME,listagg(COLUMN_NAME, ',') WITHIN GROUP (ORDER BY COLUMN_POSITION) COLUMN_NAME FROM sys.dba_ind_columns where INDEX_NAME = indexNM and TABLE_NAME = tableNM GROUP BY INDEX_NAME);
BEGIN
uniqueSTMT := 'CREATE UNIQUE INDEX';
nonUniqueSTMT := 'CREATE INDEX';
charOn := 'on';
if chkTyp.ES_UNIQUENESS = 'UNIQUE' then
tempfield := uniqueSTMT || indexNM || charOn || tableNM || '(' || tblColumn.COLUMN_NAME || ')' ;
DBMS_OUTPUT.put_line(tempfld);
end if;
END;
END;
/
Error list:
LINE/COL ERROR
-------- ------------------------------------------------------------------
9/17 PL/SQL: SQL Statement ignored
9/48 PL/SQL: ORA-00942: table or view does not exist
10/20 PL/SQL: SQL Statement ignored
10/126 PL/SQL: ORA-00942: table or view does not exist
18/1 PL/SQL: Statement ignored
18/11 PLS-00225: subprogram or cursor 'CHKTYP' reference is out of scope
Hi all, when i try to create a sample store procedure above. I hit SQL Statement ignored.
Need some help on this, Thanks alot.
You don't have access to DBA_ views (owned by SYS). Do you really need those? Switch to USER_IND_COLUMNS instead. Once you make that code work, expand it further (if necessary).
As of CHKTYP being improperly used: you declared a cursor, but never did anything with it (opened, fetched, ..., closed). On the other hand, why do you use cursors? Those are SELECT statements that return a single value (unless I'm wrong), so they might have been ordinary SELECTs (but yes, you might have to handle possible NO-DATA-FOUND exception).
Furthermore, there's no column ES_UNIQUENESS in USER_IND_COLUMNS view; what is is supposed to do? It exists in USER_INDEXES, but is called UNIQUENESS, without the ES_ prefix.
Shortly, you need to rewrite that code. Take it step by step, test frequently. Once you're sure that the first step was successful, go to the next.

Parameters wrong assignment (PL/SQL, ORACLE)

I'm trying to run below pl/sql block but I'm getting error:
set serveroutput on
declare
rowBefore VARCHAR2(32000);
myschema VARCHAR2(32000) := 'abc';
mytable VARCHAR2(32000) := 'table1';
param1 VARCHAR2(32000) := 'Tom';
begin
select count(*) into rowBefore from myschema.mytable where colA = param1;
--select count(*) into rowBefore from abc.table1 where colA = 'Tom';
DBMS_OUTPUT.PUT_LINE(rowBefore);
End;
How to correctly use my all parameters into select statement?
Update error:
Error report -
ORA-06550: linia 7, kolumna 50:
PL/SQL: ORA-00942: tabela lub perspektywa nie istnieje
ORA-06550: linia 7, kolumna 5:
PL/SQL: SQL Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
You can't use a variable as an identifier in a SQL statement. It is looking for a table that is actually called mytable - not one with the value of the variable with that name as you expect. And the same for the schema.
From the documentation:
If the statement is a SELECT statement, the PL/SQL compiler removes the INTO clause.
The PL/SQL compiler sends the statement to the SQL subsystem.
The SQL subsystem checks the syntax of the statement.
If the syntax is incorrect, the compilation of the PL/SQL unit fails. If the syntax is correct, the SQL subsystem determines the names of the tables and tries to resolve the other names in the scope of the SQL statement.
...
It tries to resolve other names, e.g. functions; but table names (and schema names, and column names) have to be valid to the SQL parser.
You have to use dynamic SQL to create a string that contains the statement, concatenating in the identifiers:
execute immediate 'select count(*) from ' || myschema ||'.'|| mytable
|| ' where colA = :value'
into rowBefore using param1;
If you print out that generated statement with dbms_output you should see it matching the commented-out version, except for the use of a bind variable for the columns value. That would also help highlight any errors - like not including whitespace between the concatenated parts of the statement, which is a common and easy mistake.
It's often a good idea to build the statement as a string variable to make such debugging easier:
declare
...
v_stmt varchar2(4000):
begin
v_stmt := 'select count(*) from ' || myschema ||'.'|| mytable
|| ' where colA = :value';
-- for debugging
dbms_output.put_line(v_stmt);
-- and run it
execute immediate vStmt into rowBefore using param1;
...
If you are really getting the identifiers passed in by a user or client you should validate them to avoid unexpected errors and SQL injection attacks. Also, if the identifiers might be case sensitive (i.e. schemas/tables created with quoted identifiers) then you may need to add double-quotes to the generated statement, and make sure the variables are the correct case.
error is ORA-942: table or view does not exists. run first below query and see if error still occurs.
-- should you use abc.table1, instead of myschema.mytable?
select count(*) rowBefore from myschema.mytable where colA = 'a';
if there is still error, then fix the SELECT statement first before you use it in the PL/SQL block.

Output results of Oracle stored proc from SQL Developer

I'm trying to call an Oracle stored proc using SQL Developer. The proc outputs results using a sys_refcursor. I right click in the proc window which brings up the Run PL/SQL window. When I choose the proc I want it creates all the input params etc for me. Below is the code I'm using to try and loop through the sys_refcursor and output the results, but I'm getting an error on the 'v_rec v_Return%rowtype;' line :
ORA-06550: line 6 column 9:
PLS-00320: the declaration of the type of this expression is incomplete or malformed.
ORA-06550: line 6 column 9:
PL/SQL: Item ignored
vendor code 6550
I found the looping code on a couple of other websites and it seems to be the way to do it but it's not working for me no matter what I try. Another question - on the DBMS_OUTPUT.PUT_LINE('name = ' || v_rec.ADM) am I referencing the v_rec correctly i.e. is v_rec."column_name" the correct way??
I'm not that used to Oracle and have never used SQL plus. Any suggestions appreciated.
DECLARE
P_CAE_SEC_ID_N NUMBER;
P_PAGE_INDEX NUMBER;
P_PAGE_SIZE NUMBER;
v_Return sys_refcursor;
v_rec v_Return%rowtype;
BEGIN
P_CAE_SEC_ID_N := NULL;
P_PAGE_INDEX := 0;
P_PAGE_SIZE := 25;
CAE_FOF_SECURITY_PKG.GET_LIST_FOF_SECURITY(
P_CAE_SEC_ID_N => P_CAE_SEC_ID_N,
P_PAGE_INDEX => P_PAGE_INDEX,
P_PAGE_SIZE => P_PAGE_SIZE,
P_FOF_SEC_REFCUR => v_Return
);
-- Modify the code to output the variable
-- DBMS_OUTPUT.PUT_LINE('P_FOF_SEC_REFCUR = ');
loop
fetch v_Return into v_rec;
exit when v_Return%notfound;
DBMS_OUTPUT.PUT_LINE('name = ' || v_rec.ADM);
end loop;
END;
Your problem is here:
v_Return sys_refcursor;
v_rec v_Return%rowtype;
v_Return is a cursor variable and has no specific structure (list of columns), so v_Return%rowtype is not a valid record structure to declare v_rec. It is even possible for different calls to the procedure to return cursors with different structures.
You know what you are expecting the structure of the returned cursor to be (but Oracle doesn't) so you need to explicitly define the appropriate record structure e.g.
type t_row is record (empno number, ename varchar2(30));
v_rec t_row;
You need a strongly typed ref cursor to be able to define it as a %ROWTYPE.
Example here
#Tony Andrews thanks for this it gave me a better idea where I was going wrong. Still having problems though - here's a shortened version of my proc. It's a bit complex in that it's selecting all fields from a subquery and 2 other values:
open p_fof_sec_refcur for
SELECT *
FROM(
SELECT securities.*, rownum rnum, v_total_count
FROM
(
SELECT
CFS.CAE_SEC_ID,
CFS.FM_SEC_CODE,
...
FROM
CAEDBO.CAE_FOF_SECURITY CFS
INNER JOIN caedbo.CAE_DATA_SET_ELEMENT CDSE_STAT
ON (CDSE_STAT.DATA_SET_ELEMENT_ID = CFS.APPR_STATUS)
...
WHERE APPR_STATUS = NVL(p_appr_status, APPR_STATUS)
...
)securities
)
WHERE rnum between v_pgStart and v_pgEnd;
I explicitly defined the output structure as below to match the return fields from the proc but I'm still getting an error:
v_Return sys_refcursor;
type t_row is record (CAE_SEC_ID NUMBER,FM_SEC_CODE VARCHAR2(7),...rnum number, v_total_count number);
v_rec t_row;
The error I get is
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
ORA-06512: at line 45
I'm just wondering is the "rownum rnum, v_total_count" part tripping me up. I'm pretty sure I have all the other fields in the output structure correct as I copied them directly from the proc.

Resources