Good Day,
I have a PL-SQL query as follows. I'm trying to execute a query and store the results into a variable. So far I have this query which works:
SELECT DECODE(COUNT(*), 0, 'N', 'Y') REC_EXISTS
FROM
(SELECT
COUNT(*) AS TOTAL_COUNT
FROM DEV.BASEOBJECT INNER JOIN
DEV.ANIMAL ON DEV.BASEOBJECT.ID = DEV.ANIMAL.BASEOBJECT_ID
GROUP BY DEV.BASEOBJECT.ID,
DEV.BASEOBJECT.FIRST_NAME,
DEV.BASEOBJECT.LAST_NAME,
DEV.BASEOBJECT.CITY,
DEV.BASEOBJECT.STATE,
DEV.BASEOBJECT.ZIP,
DEV.ANIMAL.ID,
DEV.ANIMAL.NAME,
DEV.ANIMAL.BREED,
DEV.ANIMAL.DATE_OF_BIRTH,
DEV.ANIMAL.GENDER,
DEV.ANIMAL.SPECIES
HAVING (COUNT(*) > 1));
But when I try to save the results into a variable with this query:
DECLARE
v_name VARCHAR2(2);
BEGIN
SELECT DECODE(COUNT(*), 0, 'N', 'Y') REC_EXISTS
INTO v_name
FROM
(SELECT
COUNT(*) AS TOTAL_COUNT
FROM DEV.BASEOBJECT INNER JOIN
DEV.ANIMAL ON DEV.BASEOBJECT.ID = DEV.ANIMAL.BASEOBJECT_ID
GROUP BY DEV.BASEOBJECT.ID,
DEV.BASEOBJECT.FIRST_NAME,
DEV.BASEOBJECT.LAST_NAME,
DEV.BASEOBJECT.CITY,
DEV.BASEOBJECT.STATE,
DEV.BASEOBJECT.ZIP,
DEV.ANIMAL.ID,
DEV.ANIMAL.NAME,
DEV.ANIMAL.BREED,
DEV.ANIMAL.DATE_OF_BIRTH,
DEV.ANIMAL.GENDER,
DEV.ANIMAL.SPECIES
HAVING (COUNT(*) > 1));
END
I get an error:
ERROR
ORA-06550: line 1, column 8:
PLS-00103: Encountered the symbol "" when expecting one of the following:
begin function package pragma procedure subtype type use
<an identifier> <a double-quoted delimited-identifier> form
current cursor
The symbol "" was ignored.
Eventually, this is going to be a stored procedure, but I don't have that part ready yet, because I wanted to verify that what I have is working so far.
TIA,
coson
How are you running this? What tools are you using? I think that the problem is your tool/IDE is trying to compile this as a function/procedure. This code looks ok and would probably run with no problems if you ran it as a script in SQL*Plus. If you run this as a script, you should add a dbmbs_output.put_line(v_name) after the query to see the result.
Related
I am trying to set the default value of an item in Oracle APEX 4.2 by selecting the first value in a table having the specified VIDEO_ID. In the item, under the Default section I have set Default Value Type = PL/SQL EXPRESSION, and in the Default Value block I have entered
SELECT UNIQUE_ALLEGATION_ID
FROM (
SELECT UNIQUE_ALLEGATION_ID
FROM TBL_UNIQUE_ALLEGATION
WHERE VIDEO_ID = :P2_VIDEO_SELECT) A
WHERE ROWNUM <= 1
ORDER BY ROWNUM;
This code works just fine in my Oracle editor (if I replace :P2_VIDEO_SELECT with a value; and I am positive that :P2_VIDEO_SELECT is properly set).
However, when I run the page, I get the following error:
ORA-06550: line 1, column 43: PLS-00103: Encountered the symbol "SELECT" when expecting one of the following:
( - + case mod new not null <an identifier> <a double-quoted delimited-identifier> <a bind variable>
continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date
pipe
Remember that Apex attributes that accept SQL or PL/SQL fragments must be executed by the Apex at runtime, and that these must necessarily be embedded in wrapping code that must compile and execute at runtime.
So, for example, a source that is of type "PL/SQL Expression" will probably be executed in something like this:
declare
temp_var varchar2(4000);
begin
temp_var := (
SELECT UNIQUE_ALLEGATION_ID
FROM (
SELECT UNIQUE_ALLEGATION_ID
FROM TBL_UNIQUE_ALLEGATION
WHERE VIDEO_ID = :P2_VIDEO_SELECT) A
WHERE ROWNUM <= 1
ORDER BY ROWNUM
);
--use temp_var somewhere
end;
Obviously, the above code is not expected to work, which is why you're seeing an error like ORA-06550.
I am trying to create dynamic table within procedure but i am getting error please
tell me whats the error
CREATE OR REPLACE PROCEDURE check_sms_bundle_25 (
MON VARCHAR2,
YEAR_P VARCHAR2 DEFAULT TO_CHAR (SYSDATE, 'YY'),
QUARTER VARCHAR2,
TYPE VARCHAR2 DEFAULT 'NEW')
IS
BEGIN
IF UPPER (QUARTER) = 1
THEN
EXECUTE IMMEDIATE 'BEGIN CREATE OR REPLACE TABLE (''SMS_Bundle_25_'''|| UPPER (MON)|| '''_Q'''|| UPPER (QUARTER)|| '||''_''||'''|| UPPER (YEAR_P)|| ''')
AS
SELECT customer_id, otxact
FROM ordertrailer INNER JOIN orderhdr_all ON ohxact = otxact
WHERE sncode = 343 AND ohentdate = ''1-aug-2014'' AND ohstatus = ''IN''
END';
END IF;
END;
The error msg is
ORA-06550: line 2, column 4: PLS-00103: Encountered the symbol
"CREATE" when expecting one of the following:
begin case declare exit for goto if loop mod null pragma raise
return select update while with << close current delete
fetch lock insert open rollback savepoint set sql execute commit
forall merge pipe ORA-06512: at "FI_SDINE.CHECK_SMS_BUNDLE_25", line 9
ORA-06512: at line 1
As well as 'or replace' not being valid as part of the create table syntax, you're enclosing the DDL statement inside another anonymous PL/SQL block, you're trying to put the table name inside parentheses, and you're including quote marks - which are not allowed in an (unquoted) object identifier. So if you pass in argukments AUG, 14, 1 NEW then your dynamic statement is trying to run:
BEGIN CREATE OR REPLACE TABLE ('SMS_Bundle_25_'AUG'_Q'1||'_'||'14')
AS
SELECT customer_id, otxact
FROM ordertrailer INNER JOIN orderhdr_all ON ohxact = otxact
WHERE sncode = 343 AND ohentdate = '1-aug-2014' AND ohstatus = 'IN'
END
The BEGIN/END make is a block and the DDL statement isn't valid in PL/SQL; that's why you're having to use execute immediate in the first place. If you change your construction to:
EXECUTE IMMEDIATE 'CREATE TABLE SMS_Bundle_25_'|| UPPER (MON)
|| '_Q'|| UPPER (QUARTER) ||'_' || UPPER (YEAR_P)|| '
AS
SELECT customer_id, otxact
FROM ordertrailer INNER JOIN orderhdr_all ON ohxact = otxact
WHERE sncode = 343 AND ohentdate = ''1-aug-2014'' AND ohstatus = ''IN''');
you'd then be trying to run:
CREATE TABLE SMS_Bundle_25_AUG_Q1_14
AS
SELECT customer_id, otxact
FROM ordertrailer INNER JOIN orderhdr_all ON ohxact = otxact
WHERE sncode = 343 AND ohentdate = '1-aug-2014' AND ohstatus = 'IN'
which at least looks more viable, assuming the tables you're selecting from exist. No idea why you're passing the year and quarter numbers as strings or applying upper() to them. And presumably you really want the select to be filtered on the same year and month as the table name.
It's useful to display the command you're trying to execute, for example with dbms_output, to see exactly what you've created; and you can then also run that manually to see where it's going wrong more clearly.
But as noted in comments, it's unusual to create objects from a procedure like this. Your schema should usually be static, not modified on the fly. You won't be able to refer to this table from other code unless that is also being built dynamically. You seem to be creating a table as a snapshot of the other tables; a view or a materialised view might be more appropriate. But I'm not really sure why you're doing this so it's not entirely clear what you should be doing instead.
I have a Procedure like this,
create or replace
PROCEDURE SP_PROOF
( proof_id IN NUMBER
, Type1 IN VARCHAR2
, StatementType IN NUMBER
, Resultset OUT NUMBER
) AS
BEGIN
IF StatementType = 1 Then
INSERT INTO ID_Proof (proofid,Id_type)
VALUES (proof_id, Type1);
ELSIF StatementType=2 THEN
SELECT proofid,Id_type Into Resultset FROM ID_Proof;
ELSIF StatementType=3 THEN
UPDATE ID_Proof SET Id_type = Type1 WHERE proofid = proof_id;
ELSIF StatementType=4 THEN
DELETE FROM ID_Proof WHERE proofid = proof_id;
end if;
end;
Im getting an error like this,
Error(14,1): PL/SQL: SQL Statement ignored
Error(14,64): PL/SQL: ORA-00947: not enough values
Please help me to correct the error.
Line 14 is:
SELECT proofid,Id_type Into Resultset FROM ID_Proof;
You are selecting two values, proofid and Id_type, into a single scalar variable Resultset. But you also have no filter, so even if you changed that to select a single value then you'd get a too-many-rows error if there was more than one row in the table (and no-data-found if the table is empty).
It isn't clear what you want to happen; perhaps you want select id_type into resultset from id_proof, but from the parameters id_type is a string - so selecting that into a number variable is likely to fail too. Or perhaps you want all IDs for the specified type, in which case the type of result set would need to be a table type or a ref cursor.
Having separate procedures and functions would be probably be clearer, too.
I have written a PL/SQL Procedure which compares data between two tables and print the difference if any, but the twist is the table names to the procedure is dynamic. Here is the procedure
create or replace PROCEDURE compareTables(
tabA IN VARCHAR2, tabB IN VARCHAR2) AS
cur_tab_name USER_TABLES%ROWTYPE;
lv_sql varchar2(4000);
lv_sql2 varchar2(4000);
BEGIN
--SELECT TABLE_NAME INTO cur_tab_name FROM USER_TABLES WHERE TABLE_NAME = tabA;
lv_sql2 := 'SELECT TABLE_NAME FROM USER_TABLES WHERE TABLE_NAME = :b_tabA';
EXECUTE IMMEDIATE lv_sql2 INTO cur_tab_name USING tabA;
<<child>>
DECLARE
TYPE cursor_ref IS REF CURSOR;
cur_comp_result cursor_ref;
rec_comp_result cur_tab_name.TABLE_NAME%rowtype;
BEGIN
lv_sql := 'SELECT * FROM '||tabA||' MINUS SELECT * FROM '||tabB;
OPEN cur_comp_result FOR lv_sql;
LOOP
FETCH cur_comp_result INTO rec_comp_result;
EXIT WHEN cur_comp_result%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(rec_comp_result.empid || '' || rec_comp_result.name);
END LOOP;
CLOSE cur_comp_result;
Exception
When others then
dbms_output.put_line('The Problem is '||sqlerrm);
END;
END compareTables;
Now the problem is when I compile this procedure I am getting the following error
Error at line 14: PLS-00310: with %ROWTYPE attribute, 'CUR_TAB_NAME.TABLE_NAME' must name a table, cursor or cursor-variable
line 14:rec_comp_result cur_tab_name.TABLE_NAME%rowtype;
how will I solve it?
*NB: I don't have oracle installed in my system. I am using Oracle Apex Online tool which uses
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 and
PL/SQL Release 11.2.0.3.0
As a test, go to the last line, and after the semicolon, hit enter.
I know that Pro*C in particular will gag without a line terminator at the end of the file.
You may be encounting that issue.
Outside the scope of your question consider
SELECT columns
FROM TABLE1
MINUS
SELECT columns
FROM TABLE2
and
SELECT columns
FROM TABLE2
MINUS
SELECT columns
FROM TABLE1
Use: cur_tab_name.table_name. The variable CUR_TAB_NAMEis of type USER_TABLE%ROWTYPE, thus it has several fields.
DECLARE
v_name A.TRANSACTION_TYPE%TYPE :='SALARY';
v_salary A.SALARY%TYPE := 1000;
BEGIN
update A set v_name= v_salary where EMPID = 517;
-- PL/SQL: ORA-00904: "v_name": invalid identifier
--update A set SALARY = 1000 where EMPID = 517;
END;
/
My idea is to update table columns , but these column names are stored in variable. Is there any way to pass column names from variable ? Is there any options apart from Execute Immediate
Not sure if this will work in your situation, but I've written solutions where I wrote a script in SQLPlus and it "wrote" (using dbms_output.put_line or even just prompt) another script that did queries, and the columns/tables in those queries was determined by the logic in the SQLPlus script. Then I would execute as a script the output from my first script, and it would execute dynamically generated queries without ever needing execute immediate.
The following idea may work for multiple columns that are typed the same... As written, it will update all columns every time for a given record, but only the column specified by v_name will be changed to the value set in v_value; the other columns are simply updated to their existing value. The idea can be played with using DECODE, NVL or other similar conditional operators.
declare
v_name varchar2(20):= 'SAL';
v_value emptest.sal%TYPE := 5000;
begin
update emptest
set sal = ( select case when v_name = 'SAL' then v_value else sal end from dual),
comm = ( select case when v_name = 'COMM' then v_value else comm end from dual)
where empno = 7369;
commit;
end;