Error when comparing values in Oracle - oracle

I write simple procedure.
DECLARE
connection_id LINE.CONNECTION_ID%TYPE := 11009;
tmp_integer INTEGER;
BEGIN
SELECT COUNT(*) INTO tmp_integer FROM LINE WHERE LINE.CONNECTION_ID = 11009;
DBMS_OUTPUT.PUT_LINE(connection_id);
DBMS_OUTPUT.PUT_LINE(tmp_integer);
END;
Result of the launch:
11009
3
It is good result. I have only 3 rows where CONNECTION_ID is 11009.
After modification:
DECLARE
connection_id LINE.CONNECTION_ID%TYPE := 11009;
tmp_integer INTEGER;
BEGIN
SELECT COUNT(*) INTO tmp_integer FROM LINE WHERE LINE.CONNECTION_ID = connection_id;
DBMS_OUTPUT.PUT_LINE(connection_id);
DBMS_OUTPUT.PUT_LINE(tmp_integer);
END;
But in this case I gain strange result:
11009
30997
Where is the mistake?

Try changing the name of your PL/SQL variable to be different from the column name in the table, e.g. v_connection_id.

Related

Show the output of a procedure in Oracle

The procedure uses the previous function to display the list of the products: num, designation and mention on the application.
SET SERVEROUTPUT ON;
CREATE OR REPLACE FUNCTION STORE(num_produit IN INTEGER) RETURN VARCHAR AS
N INTEGER := 0;
incre INTEGER := 0;
BEGIN
SELECT SUM(qte) INTO N FROM Ligne_Fact WHERE num_produit = produit;
IF N > 15 THEN
RETURN 'fort';
ELSIF N > 11 THEN
RETURN 'moyen';
END IF;
RETURN 'faible';
END;
/
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_VAR VARCHAR2(256);
BEGIN
SELECT num, designation, STORE(num) INTO SOME_VAR FROM Produit;
dbms_output.enable();
dbms_output.put_line('result : '|| SOME_VAR);
END;
/
BEGIN
SHOW_PRODUITS;
END;
/
I am sure that all the tables are filled with some dummy data, but I am getting the following error:
Function STOCKER compiled
Procedure AFFICHER_PRODUITS compiled
LINE/COL ERROR
--------- -------------------------------------------------------------
4/4 PL/SQL: SQL Statement ignored
4/56 PL/SQL: ORA-00947: not enough values
Errors: check compiler log
Error starting at line : 28 in command -
BEGIN
AFFICHER_PRODUITS;
END;
Error report -
ORA-06550: line 2, column 5:
PLS-00905: object SYSTEM.SHOW_PRODUITS is invalid
ORA-06550: line 2, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
The first major mistake you've made is to create your objects in SYSTEM schema. It, just like SYS, are special and should be used only for system maintenance. Create your own user and do whatever you're doing there.
As of your question: select returns 3 values, but you're trying to put them into a single some_var variable. That won't work. Either add another local variables (for num and designation), or remove these columns from the select:
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_VAR VARCHAR2(256);
BEGIN
SELECT STORE(num) INTO SOME_VAR FROM Produit; --> here
dbms_output.enable();
dbms_output.put_line('result : '|| SOME_VAR);
END;
/
Code, as you put it, presumes that produit contains a single record (it can't be empty nor it can have 2 or more rows because you'll get various errors).
Maybe you wanted to access all rows; in that case, consider using a loop, e.g.
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_VAR VARCHAR2(256);
BEGIN
FOR cur_r IN (SELECT num, designation, STORE(num) some_var FROM Produit) LOOP
dbms_output.put_line(cur_r.num ||', '|| cur_r.designation ||', result : '|| cur_r.some_var);
END LOOP;
END;
/
Then
set serveroutput on
BEGIN
SHOW_PRODUITS;
END;
/
You are trying to compile some stored routine which calls another stored routine named AFFICHER_PRODUITS and that routine calls SHOW_PRODUITS but SHOW_PRODUITS does not compile, hence the error. (By the way, it is recommended not to create your own stored routines in the SYSTEM schema.)
SHOW_PRODUITS does not compile because of this line:
SELECT num, designation, STORE(num) INTO SOME_VAR FROM Produit;
It appears that you want to get the query results as a string. In order to do that, you need to concatenate the column values, i.e.
SELECT num || designation || STORE(num) INTO SOME_VAR FROM Produit;
Of-course if all you want to do is display the query results, using DBMS_OUTPUT, you can declare a separate variable for each column.
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_NUM Produit.num%type;
SOME_DES Produit.designation%type;
SOME_VAR VARCHAR2(6);
BEGIN
SELECT num
,designation
,STORE(num)
INTO SOME_NUM
,SOME_DES
,SOME_VAR
FROM Produit;
dbms_output.enable();
dbms_output.put_line('result : ' || SOME_NUM || SOME_DES || SOME_VAR);
END;
Note that if the query returns more than one row, you will [probably] need to use a cursor.
CREATE OR REPLACE PROCEDURE SHOW_PRODUITS IS
SOME_NUM Produit.num%type;
SOME_DES Produit.designation%type;
SOME_VAR VARCHAR2(6);
--
CURSOR c1 IS
SELECT num, designation, STORE(num) FROM Produit;
BEGIN
OPEN c1;
LOOP
FETCH c1 INTO SOME_NUM, SOME_DES, SOME_VAR;
EXIT WHEN c1%NOTFOUND;
dbms_output.put_line('result : ' || SOME_NUM || SOME_DES || SOME_VAR);
END LOOP;
CLOSE c1;
END;

Error PLS-00428: an INTO clause is expected in this SELECT statement

I just want to show USU_USERS table between a declare procedure but it's shows this error when I try to compile
DECLARE
ID_UNICO VARCHAR(200) := 'H3LP';
BEGIN
DECLARE
VID VARCHAR2(200);
VID_USER VARCHAR2(200);
BEGIN
VID := ID_UNICO;
VID_USER := 'SOPORTE';
USR_SP_USERS.CREATE(
VID => VID,
VID_USER => VID_USER,
);
END;
SELECT * from USU_USERS;
END;
NOTE : THIS TABLE HAS MORE THAN ONE ROWS.
PL/SQL is a server-side language only, and as such there's no way to "show" the results of a SELECT statement anywhere. Your SELECT statement needs to put the values it retrieves from the database into a variable or variables. Let's try to give you something which will work:
DECLARE
strID_UNICO VARCHAR(200) := 'H3LP';
strVID VARCHAR2(200);
strVID_USER VARCHAR2(200);
rowUSU_USERS USU_USERS%ROWTYPE;
BEGIN
strVID := strID_UNICO;
strVID_USER := 'SOPORTE';
USR_SP_USERS.CREATE(VID => strVID,
VID_USER => strVID_USER);
SELECT *
INTO rowUSU_USERS
FROM USU_USERS;
END;
Note that if the table USU_USERS has more than one row in it this code will fail. Assuming, though, that USU_USERS has only a single row in it, you could then use DBMS_OUTPUT.PUT_LINE to output the various fields in rowUSU_USERS.

Oracle: Declare multiple constants and use them in WHERE clause

I perform daily extractions from the same table. The only thing that ever changes is the range of a column called SAMPLE_ID, so I would like to assign a fixed value to two variables: id_min and id_max so that I can update their values before running the query.
I tried the following:
DECLARE
id_min CONSTANT INTEGER := 17778;
id_max CONSTANT INTEGER := 17803;
BEGIN
SELECT
*
FROM
MDB.SCORES
WHERE
SAMPLE_ID BETWEEN id_min AND id_max;
END;
I expected this code to use the numbers assigned to id_min and id_max as the lower and upper bounds of the BETWEEN function in the WHERE clause, but I'm getting this message:
ORA-06550: line 6, column 5:
PLS-00428: an INTO clause is expected in this SELECT statement
It seems someone ran into something similar in this thread, but I do not understand the solutions provided.
Since you are running a PL/SQL code, you cannot just run a SELECT query without doing something with it.
There are some ways on dealing with select queries in PL/SQL.
1) INTO clause, where you take the row returned from the query and assign them to variables. *Notice is said row, not rows. If your query returns more then one row you cannot use INTO clause since it will generate TO_MANY_ROWS exception.
DECLARE
id_min CONSTANT INTEGER := 17778;
id_max CONSTANT INTEGER := 17803;
variable1 your_variable_type;
variable2 your_variable_type;
variable3 your_variable_type;
BEGIN
SELECT
*
INTO
variable1,
variable2,
variable3
FROM
MDB.SCORES
WHERE
SAMPLE_ID BETWEEN id_min AND id_max;
---- DO SOMETHING WITH YOUR VARIABLES ----
END;
2) FOR loop if you have one or many rows.
DECLARE
id_min CONSTANT INTEGER := 17778;
id_max CONSTANT INTEGER := 17803;
BEGIN
FOR c IN (
SELECT
*
FROM
MDB.SCORES
WHERE
SAMPLE_ID BETWEEN id_min AND id_max
) LOOP
---- DO SOMETHING WITH YOUR VARIABLES ----
---- ACCESS A COLUMN ----
c.column_name;
END LOOP;
END;
3) CURSOR declaring.
DECLARE
id_min CONSTANT INTEGER := 17778;
id_max CONSTANT INTEGER := 17803;
v_cursor SYS_REFCURSOR;
your_variables
...
BEGIN
OPEN v_cursor FOR
SELECT
*
FROM
MDB.SCORES
WHERE
SAMPLE_ID BETWEEN id_min AND id_max;
LOOP
FETCH v_cursor INTO your_variables;
EXIT WHEN v_cursor%NOTFOUND;
---- DO SOMETHING WITH YOUR VARIABLES ----
END LOOP;
END;
Once you are between BEGIN and END you are no longer in SQL, but in PLSQL.
In PL/SQL there is no just select statement, there is a "select ... INTO ..." statement instead.
In other words, the database wants from you a variable to save the results to.
Or you might use a loop in order to operate with data.
Below is the loop example to print the data from some_column out
DECLARE
id_min CONSTANT INTEGER := 17778;
id_max CONSTANT INTEGER := 17803;
BEGIN
for score in (SELECT *
FROM MDB.SCORES
WHERE SAMPLE_ID BETWEEN id_min AND id_max) loop
dbms_output.put_line(sc.some_column_name);
end loop;
END;
You might find it simpler to use bind variables, and not run your query in PL/SQL at all.
var id_min NUMBER
var id_max NUMBER
begin
:id_min := 17778;
:id_max := 17803;
end;
/
SELECT
*
FROM
MDB.SCORES
WHERE
SAMPLE_ID BETWEEN :id_min AND :id_max;
I did not realize DECLARE would require PL/SQL. I found it easier to do the following using DEFINE.
DEFINE id_min = 17778
DEFINE id_max = 17803;
SELECT
*
FROM
MDB.SCORES
WHERE
SAMPLE_ID BETWEEN &id_min AND &id_max;

PL/SQL Record populate

I have a record as following and I want to populate this with a for loop.
declare
type ch_type is table of record(id number, name varchar2(50));
type ch_type_tab is table of ch_type;
rec_typr ch_type_tab;
begin
for i in (select * from emp) loop
rec_typr.id := i.emp_id;
rec_typr.name := i.first_name;
end loop;
for i in rec_typr.first..rec_typr.last
loop
dbms_output.put_line(rec_typr(i).id);
end loop;
end;
but I get the error:
PLS:0302 component first must be declared.
Can you help me with this?
Two things are problematic in your code.
1) type ch_type is table of record is syntactically incorrect. You must first declare a record and then define its collection type.
2) Using implicit cursor loop is not an efficient method to load a collection and definitely can't be done the way you're trying to do. Use much simpler BULK COLLECT method instead.
declare
type ch_type is record(id number, name varchar2(50));
type ch_type_tab is table of ch_type;
rec_typr ch_type_tab;
begin
select emp_id,first_name bulk collect into
rec_typr from emp;
for i in rec_typr.first..rec_typr.last
loop
dbms_output.put_line(rec_typr(i).id);
end loop;
end;
/
Output
1
2
3
4
5
6
7
8
9
10
11
12
13
14
PL/SQL procedure successfully completed.
EDIT
I need to populate the record through a loop not through bulk collect.
Is it any way?
Yes, there is. But, it is less efficient than the method described above.
declare
type ch_type is record(id number, name varchar2(50));
type ch_type_tab is table of ch_type;
rec_typr ch_type_tab := ch_type_tab();
i INTEGER := 1;
begin
rec_typr.extend;
for rec in
(
select emp_id,first_name bulk collect into
rec_typr from emp
)
loop
rec_typr(i).id := rec.emp_id;
rec_typr(i).name := rec.first_name;
rec_typr.extend;
i := i + 1;
end loop;
for i in rec_typr.first..rec_typr.last
loop
dbms_output.put_line(rec_typr(i).id);
end loop;
end;
/

How do I insert variable values in to a table record in an oracle procedure

How do I insert variable values in to a table record in an oracle procedure?
if pCount1=0 then
insert into opions(qid,otext,oflag)
(rec.pQid, rec.pOptions, rec.pCorrect);
end if;
where rec.* are the variables of the procedure
Are you looking for one of these statements (which are functionally equivalent)?
insert into opions(qid,otext,oflag)
values (rec.pQid, rec.pOptions, rec.pCorrect);
insert into opions(qid,otext,oflag)
select rec.pQid, rec.pOptions, rec.pCorrect from dual;
This assumes that rec is defined somewhere else in the stored procedure. Otherwise, you need to use the second form with rec defined in the from clause.
Try:
CREATE OR REPLACE PROCEDURE SOME_PROC AS
nQid NUMBER;
strOptions VARCHAR2(100);
strCorrect VARCHAR2(1);
BEGIN
nQid := 1;
strOptions := 1234;
strCorrect := 'Y';
INSERT INTO OPIONS(qid, otext, oflag)
VALUES (nQid, strOptions, strCorrect);
END SOME_PROC;
Best of luck.

Resources