How to use variable of declare at the where of select? - oracle11g

How to use variable of declare at the where of select ?
CREATE TABLE student (
id smallint PRIMARY KEY,
first_name VARCHAR(80) NOT NULL,
last_name VARCHAR(80) NOT NULL);
insert into student VALUES(10,'AA','A01');
insert into student VALUES(30,'BB','B01');
---MSSQL OK
declare #v_first varchar(10);
set #v_first='AA';
select * from student where first_name=#v_first;
---ORACLE --ERROR
declare v_first varchar2(10);
BEGIN
v_first :='AA';
select * from student where first_name= v_first;
END;
---=> MESSAGE
ORA-06550: line 4 , column 3 :
PLS-00428: 在此 SELECT 敘述句中預期會出現一個 INTO 子句
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:

The example you gave for MSSQL is a different table, but assuming DEPT_ID from USER_LIST is a NUMBER too... SQL will automatically convert the string to compare...
You need to cast the id to a number. Is there a reason you are declaring a varchar variable right before comparing it against a number?
declare v_id varchar2(2);
BEGIN
v_id :='30';
select * from student where id= TO_NUMBER(v_id);
END;
or change the declare and the assignment...
declare v_id NUMBER;
BEGIN
v_id :=30;
select * from student where id= v_id;
END;
basically, what the link I added in the comments below said.. from user tvm.. "You cannot use SELECT without INTO clause in PL/SQL. The output of the SELECT must be stored somewhere. Eg. table or variable or perhaps a record. See example below how to store result of the SELECT statement into record."
DECLARE
v_id number;
v_result Student%ROWTYPE;
BEGIN
v_id := 30;
SELECT * INTO v_result
FROM Student
WHERE id = v_id;
END;
Then you need to do something with v_result... other option shown is to call straight SQL - all depends on how you call and consume the data..

Related

How to fetch row of unknown ROWTYPE in PL/SQL?

I have table in oracle with definitions of lists. Each definition is sql string, that returns table with 'd' and 'r' columns. I want get some 'd' value by 'r' value.
Example:
My query string is: SELECT SOME_COLUMN d, SOME_COLUMN2 r from SOME_TABLE order by 1
My PL/SQL code is:
DECLARE
query_str VARCHAR2(2000) := 'SELECT SOME_COLUMN d, SOME_COLUMN2 r from SOME_TABLE order by 1';
return_str VARCHAR2(2000);
TYPE LovCurTyp IS REF CURSOR;
v_lov_cursor LovCurTyp;
--And there is my problem:
lov_record UNKNOWN_TYPE_OF_SOME_TABLE%ROWTYPE;
BEGIN
OPEN v_lov_cursor FOR query_str;
LOOP
FETCH v_lov_cursor INTO lov_record;
EXIT WHEN v_lov_cursor%NOTFOUND;
--Get return_str here
END LOOP;
CLOSE v_lov_cursor;
return return_str;
END;
So my question is: How to fetch row of unknown ROWTYPE or maybe there is another way to do something like I describe?

I want to use out parameter ,but I am not getting the proper syntax of doing so,:ORA-00900: invalid SQL statement

Problem definition: Create a procedure which will display the employees in descending order of employee name of
computer department.
CREATE OR REPLACE PROCEDURE pr_disp (name OUT VARCHAR2,
age OUT NUMBER,
dep OUT VARCHAR,
salary OUT NUMBER)
AS
CURSOR c
IS
SELECT name,
age,
department,
salary
FROM enployee2
WHERE department = 'Computer'
ORDER BY name DESC;
this_name enployee2.name%TYPE;
this_age enployee2.age%TYPE;
this_dep enployee2.department%TYPE;
this_sal enployee2.salary%TYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1
INTO this_name,
this_age,
this_dep,
this_sal;
DBMS_OUTPUT.put_line (
this_name || ' ' || this_age || ' ' || this_dep || '
' || this_sal);
EXIT WHEN c1%NOTFOUND;
END LOOP;
CLOSE c1;
END;
/
Maybe there is a problem in my execution part...
execution part:
variable nm varchar2(50);
variable age number
variable dep varchar2(50);
variable sal number;
execute pr_disp(nm,age,dep,sal);
.The error comes when I execute the code is :ORA-00900: invalid SQL statement
Your code has several errors. Please see below to find out what and where:
Table Creation:
create table enployee2( name VARCHAR2(100),
age NUMBER,
department VARCHAR2(100),
salary NUMBER
);
INSERT INTO enployee2 VALUES ('AAA',32,'Computer',2344);
INSERT INTO enployee2 VALUES ('BBB',42,'Computer',4400);
insert into enployee2 values ('CCC',21,'Computer',2454);
Procedure:
Create OR REPLACE PROCEDURE pr_disp(
name OUT VARCHAR2,
age OUT NUMBER,
dep OUT VARCHAR,
salary OUT NUMBER)
AS
CURSOR c --<-- Your cursor name is `C` but you used it as `C1` below while opening and closing
IS
SELECT name,
age,
department,
salary
FROM enployee2
WHERE department ='Computer'
ORDER BY name DESC;
this_name enployee2.name%type;
this_age enployee2.age%type;
this_dep enployee2.department%type;
this_sal enployee2.salary%TYPE;
BEGIN
OPEN c; --<--Opening `C1` while your cursor name is `C`
LOOP
FETCH c INTO this_name,this_age,this_dep,this_sal;
dbms_output.put_line(this_name||' '||this_age||' '||this_dep||' '||this_sal);
EXIT WHEN c%NOTFOUND; --<--Exiting `C1` while your cursor name is `C`
END LOOP;
CLOSE c; --<--Closing `C1` while your cursor name is `C`
END;
/
Execution:
DECLARE
nm VARCHAR2(50);
age NUMBER;
dep VARCHAR2(50);
sal NUMBER;
BEGIN
pr_disp(nm,age,dep,sal);
END;
You have to write a PL/SQL-Block like this:
DECLARE
nm VARCHAR2 (50);
age NUMBER; -- here you were missing a semi-colon
dep VARCHAR2 (50);
sal NUMBER;
BEGIN
pr_disp (nm,
age,
dep,
sal);
END;
I would assume your stored procedure is invalid because of compilation errors. Try compiling again and check the messages.
You can also check the status with:
select status from user_objects where object_name='PR_DISP';
If it's INVALID you should be able to obtain error messages also via:
select * from user_errors where name = 'PR_DISP';
Maybe your table is named employee2 (not enployee2)?
Btw: What are the out parameters for? You never use them.

How to get value from nested table in pl sql table

I have created nested table as follow:
CREATE OR REPLACE TYPE EMP_NO_NAME
AS OBJECT
(
EMPNO NUMBER(4),
ENAME VARCHAR2(20),
JOB VARCHAR2(20),
MGR NUMBER(5),
HIREDATE DATE,
SAL NUMBER(7,2)
);
CREATE OR REPLACE TYPE EMP_TABLE IS TABLE OF EMP_NO_NAME;
-----------------------
CREATE TABLE NESTED_EMP
(
DEPTNO NUMBER(2) ,
EMPLOYEE EMP_TABLE
)
NESTED TABLE EMPLOYEE STORE AS NESTED_EMPLOYEE;
INSERT INTO NESTED_EMP (DEPTNO,EMPLOYEE)
VALUES (10,EMP_TABLE(EMP_NO_NAME(7839,'KING','PRESIDENT',NULL,'17-NOV-81',5000),
EMP_NO_NAME(7782,'CLARK','MANAGER',7839,'09-JUN-81',2450),
EMP_NO_NAME(7934,'MILLER','CLERK',7782,'23-JAN-82',1300)
)
);
INSERT INTO NESTED_EMP (DEPTNO,EMPLOYEE)
VALUES (20,EMP_TABLE(EMP_NO_NAME(7566,'JONES','MANAGER',7839,'02-APR-81',2975),
EMP_NO_NAME(7902,'FORD','ANALYST',7566,'03-DEC-81',3000),
EMP_NO_NAME(7369,'SMITH','CLERK',7902,'17-DEC-80',800),
EMP_NO_NAME(7788,'SCOTT','ANALYST',7566,'09-DEC-82',3000),
EMP_NO_NAME(7876,'ADAMS','CLERK',7788,'12-JAN-83',1100)
)
);
INSERT INTO NESTED_EMP (DEPTNO,EMPLOYEE)
VALUES (20,EMP_TABLE(EMP_NO_NAME(7698,'BLAKE','MANAGER',7839,'01-MAY-81',2850),
EMP_NO_NAME(7654,'MARTIN','SALESMAN',7698,'28-SEP-81',1250),
EMP_NO_NAME(7499,'ALLEN','SALESMAN',7698,'20-FEB-81',1600),
EMP_NO_NAME(7844,'TURNER','SALESMAN',7698,'08-SEP-81',1500),
EMP_NO_NAME(7900,'JAMES','CLERK',7698,'03-DEC-81',950),
EMP_NO_NAME(7521,'WARD','SALESMAN',7698,'22-FEB-81',1250)
)
);
Now I getting the value of nested table in plsql:
DECLARE
CURSOR EMPLOYEE IS
select p.* from NESTED_EMP p1 ,table(p1.employee) p;
V_EMP EMP_TABLE;
BEGIN
FOR V_EMP IN EMPLOYEE
LOOP
EXIT WHEN EMPLOYEE%NOTFOUND;
END LOOP;
FOR MYINDEX IN V_EMP.FIRST..V_EMP.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(V_EMP(MYINDEX).ENAME);
END LOOP;
END;
/
END;
Error report:
ORA-06531: Reference to uninitialized collection ORA-06512: at line 10
06531. 00000 - "Reference to uninitialized collection"
*Cause: An element or member function of a nested table or varray
was referenced (where an initialized collection is needed)
without the collection having been initialized.
*Action: Initialize the collection with an appropriate constructor
or whole-object assignment.
How to get nested table value in plsql table ?
The problem with your code is that V_EMP is not actually of type EMP_TABLE. Rather, it's an EMPLOYEE.ROWTYPE. When you initialize a cursor for loop, the variable is automatically made an appropriate ROWTYPE, overriding any previous declarations.
The good news is that, since you've already referenced the nested table in the query, you don't need to do so in the loop (it's already been exploded). Your PL/SQL can be vastly simplified:
DECLARE
CURSOR employee IS
SELECT p.*
FROM nested_emp p1 CROSS JOIN TABLE (p1.employee) p;
BEGIN
FOR v_emp IN employee LOOP
DBMS_OUTPUT.put_line (v_emp.ename);
END LOOP;
END;
/
You'll notice the EXIT WHEN was removed as well. A cursor for loop terminates automatically after the last record.
An alternative would be to not explode the nested table in the query. Then you would need two loops:
DECLARE
CURSOR employee IS
SELECT p.*
FROM nested_emp p;
BEGIN
FOR v_emp IN employee LOOP
for i in v_emp.employee.first..v_emp.employee.last loop
DBMS_OUTPUT.put_line (v_emp.employee(i).ename);
end loop;
END LOOP;
END;
/

Error in Insert function in postgresql

CREATE OR REPLACE FUNCTION InsertInformation
(
p_Name varchar(20)
,p_Address varchar(250)
,p_Mobile int
) RETURNS VOID
as $$
begin
declare v_ID int;
BEGIN
select coalesce(max(Id),0) into v_ID from Information
set; v_ID=v_ID+1
insert into Information
(
Id
,Name
,Address
,Mobile
)
values
(
v_ID
,p_Name
,p_Address
,p_Mobile
)
select v_ID;
$$
LANGUAGE plpgsql;
I convert my sql insert sp to Postgres function using online converter tool but it showing the below mention error
error showing : ERROR: syntax error at or near "insert"
LINE 16: insert into Information
This:
select coalesce(max(Id),0) into v_ID from Information
set; v_ID=v_ID+1
Is wrong.
The select isn't properly terminated, and the set itself is illegal syntax.
You probably want this:
select coalesce(max(Id),0)
into v_ID
from Information; --<< terminate with a ; here
v_id := v_id + 1; --<< terminate with a ; here
But the extra assignment isn't necessary in the first place. The above can be shortened to:
select coalesce(max(Id),0) + 1
into v_ID
from Information;
This
select v_ID;
is also wrong. To return a value use:
return v_id;
But your function is defined as returns void so you can't return anything in the first place.
But: using select coalesce(max(Id),0) + 1 to generate unique IDs is wrong and will not work correctly in a real world application.
The only correct, scalable and fast way to generate new ids is to use a sequence. Really.
The complete function (if you want to return the newly "generated" id) would look like this:
CREATE OR REPLACE FUNCTION InsertInformation(p_Name varchar(20),p_Address varchar(250),p_Mobile int)
RETURNS integer
as
$$
declare
v_ID int;
BEGIN
select coalesce(max(Id),0) + 1
into v_ID
from Information;
INSERT INTO information
(id, name, address, mobile)
VALUES
(v_id, p_name, p_address, p_mobile);
return v_id;
END;
$$
LANGUAGE plpgsql;
SQLFiddle example: http://sqlfiddle.com/#!15/4ac27/1

In pl/sql how can I execute a select statement stored in CLOB type of field?

In Oracle DB, I have a large select staetment with lots of joins and cases that is stored in a CLOB field in one of my tables.
How can i execute this statement from the CLOB?
Look into the EXECUTE IMMEDIATE syntax.
Example table:
CREATE TABLE test(id number, largedata clob);
INSERT INTO test VALUES (1, 'select name from v$database');
commit;
select * from test;
DECLARE
l_sql clob;
l_result VARCHAR2(50);
BEGIN
SELECT LARGEDATA INTO l_sql FROM TEST;
EXECUTE IMMEDIATE l_sql INTO l_result;
dbms_output.put_line(l_result);
END;
/
Output is the DB name.

Resources