简体   繁体   中英

Oracle SQL Stored Procedure missing expression error

I am writing a stored procedure that is a dynamic sequel statement to write from one intermediate table to another table. I'm pretty new at writing sql and stored procedures especially. I tried add parameters within my statement but kept receiving this error: ORA-00936: missing expression ORA-06512: at "ECH_ETL_BATCH_ID.LOOKUP_TABLE_INSERT", line 26 ORA-06512: at line 14 Process exited. I took out the parameters and hardcoded in values to just try to get it to work but I'm still receiving the same errors. Any suggestions?

create or replace PROCEDURE                                                     
LOOKUP_TABLE_INSERT 
(
P_SOURCE_DB IN VARCHAR2
, P_SOURCE_TABLE IN VARCHAR2
, P_TARGET_DB IN VARCHAR2
, P_TARGET_TABLE IN VARCHAR2
, P_COLUMN_NAME IN VARCHAR2
) AS 
l_sql_statement VARCHAR2(1000);
BEGIN


l_sql_statement :=
'INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP' || 
'(PKEY_SRC_OBJECT, VERSION_SEQ, TIMELINE_ACTION, LAST_UPDATE_DATE, SRC_ROWID, 
HUB_STATE_IND, ROLE_TP) ' || 
' SELECT MISSING_VALUES AS PKEY_SRC_OBJECT' ||
', 1 as VERSION_SEQ' ||
', 0 as TIMELINE_ACTION' ||
', INSERT_TS as LAST_UPDATE_DATE' ||
', MISSING_VALUES as "SRC_ROWID"' || 
', 1 as "HUB_STATE_IND"' ||
', MISSING_VALUES as ROLE_TP' || --P_COLUMN_NAME ||              
' FROM ECH_ETL_BATCH_ID.Ref_Intermediate ' || 
WHERE COLUMN_NM =' || ''||ROLE_TP||'' ||
'AND LOOKUP_TBL_NM =' || ''||C_S_LU_PTY_ROLE_TP||'';
dbms_output.put_line(l_sql_statement);
EXECUTE IMMEDIATE l_sql_statement;
COMMIT;
END;

EXECUTE IMMEDIATE l_sql_statement;
COMMIT;
END;

your problem is in the where condition . remove the ||

If you do a dbms_output.putline(); you ll get the statment

To add the single quotes check the solution below

the reason of error:

INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP
  (PKEY_SRC_OBJECT,
   VERSION_SEQ,
   TIMELINE_ACTION,
   LAST_UPDATE_DATE,
   SRC_ROWID,
   HUB_STATE_IND,
   ROLE_TP)
  SELECT MISSING_VALUES AS PKEY_SRC_OBJECT,
         1              as VERSION_SEQ,
         0              as TIMELINE_ACTION,
         INSERT_TS      as LAST_UPDATE_DATE,
         MISSING_VALUES as "SRC_ROWID",
         1              as "HUB_STATE_IND",
         MISSING_VALUES as ROLE_TP
    FROM ECH_ETL_BATCH_ID.Ref_Intermediate
   WHERE COLUMN_NM = || ROLE_TP ||
     AND LOOKUP_TBL_NM = || C_S_LU_PTY_ROLE_TP ||

The solution :

create or replace PROCEDURE                                                     
LOOKUP_TABLE_INSERT 
(
P_SOURCE_DB IN VARCHAR2
, P_SOURCE_TABLE IN VARCHAR2
, P_TARGET_DB IN VARCHAR2
, P_TARGET_TABLE IN VARCHAR2
, P_COLUMN_NAME IN VARCHAR2
) AS 
l_sql_statement VARCHAR2(1000);
BEGIN


l_sql_statement :=
'INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP' || 
'(PKEY_SRC_OBJECT, VERSION_SEQ, TIMELINE_ACTION, LAST_UPDATE_DATE, SRC_ROWID, 
HUB_STATE_IND, ROLE_TP) ' || 
' SELECT MISSING_VALUES AS PKEY_SRC_OBJECT' ||
', 1 as VERSION_SEQ' ||
', 0 as TIMELINE_ACTION' ||
', INSERT_TS as LAST_UPDATE_DATE' ||
', MISSING_VALUES as "SRC_ROWID"' || 
', 1 as "HUB_STATE_IND"' ||
', MISSING_VALUES as ROLE_TP' || --P_COLUMN_NAME ||              
' FROM ECH_ETL_BATCH_ID.Ref_Intermediate ' || 
' WHERE COLUMN_NM =''' ||ROLE_TP||''     
' AND LOOKUP_TBL_NM =''' ||C_S_LU_PTY_ROLE_TP|''' ';
dbms_output.put_line(l_sql_statement);
EXECUTE IMMEDIATE l_sql_statement;
COMMIT;
END;
/

The dynamic statement your (edited) code generates is:

INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP(PKEY_SRC_OBJECT, VERSION_SEQ, TIMELINE_ACTION, LAST_UPDATE_DATE, SRC_ROWID, 
HUB_STATE_IND, ROLE_TP)  SELECT MISSING_VALUES AS PKEY_SRC_OBJECT, 1 as VERSION_SEQ, 0 as TIMELINE_ACTION, INSERT_TS as LAST_UPDATE_DATE, SELECT MISSING_VALUES as "SRC_ROWID", 1 as "HUB_STATE_IND", MISSING_VALUES as ROLE_TP FROM ECH_ETL_BATCH_ID.Ref_Intermediate  WHERE COLUMN_NM =||ROLE_TP|| AND LOOKUP_TBL_NM =||C_S_LU_PTY_ROLE_TP||

or split onto multiple lines and annotated to show the issues it has:

INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP(PKEY_SRC_OBJECT, VERSION_SEQ,
  TIMELINE_ACTION, LAST_UPDATE_DATE, SRC_ROWID, HUB_STATE_IND, ROLE_TP)
SELECT MISSING_VALUES AS PKEY_SRC_OBJECT
, 1 as VERSION_SEQ
, 0 as TIMELINE_ACTION
, INSERT_TS as LAST_UPDATE_DATE
, SELECT MISSING_VALUES as "SRC_ROWID"
--^^^^^^
, 1 as "HUB_STATE_IND"
, MISSING_VALUES as ROLE_TP
FROM ECH_ETL_BATCH_ID.Ref_Intermediate
WHERE COLUMN_NM =||ROLE_TP|| AND LOOKUP_TBL_NM =||C_S_LU_PTY_ROLE_TP||
--               ^^       ^^                    ^^                  ^^

You have a few problems with that; mostly that you have sets of || embedded in the generated statement in odd places, but also that you have an extra SELECT .

This might be closer to what you want, including escaped single quotes for your embedded string literals:

l_sql_statement :=
'INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP' || 
'(PKEY_SRC_OBJECT, VERSION_SEQ, TIMELINE_ACTION, LAST_UPDATE_DATE, SRC_ROWID, HUB_STATE_IND, ROLE_TP) ' || 
' SELECT MISSING_VALUES AS PKEY_SRC_OBJECT' ||
', 1 as VERSION_SEQ' ||
', 0 as TIMELINE_ACTION' ||
', INSERT_TS as LAST_UPDATE_DATE' ||
', MISSING_VALUES as "SRC_ROWID"' || 
', 1 as "HUB_STATE_IND"' ||
', MISSING_VALUES as ROLE_TP' ||
' FROM ECH_ETL_BATCH_ID.Ref_Intermediate ' || 
' WHERE COLUMN_NM = ''ROLE_TP''' ||     
' AND LOOKUP_TBL_NM = ''C_S_LU_PTY_ROLE_TP''';

which generates (split again):

INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP(PKEY_SRC_OBJECT, VERSION_SEQ,
  TIMELINE_ACTION, LAST_UPDATE_DATE, SRC_ROWID, HUB_STATE_IND, ROLE_TP)
SELECT MISSING_VALUES AS PKEY_SRC_OBJECT
, 1 as VERSION_SEQ
, 0 as TIMELINE_ACTION
, INSERT_TS as LAST_UPDATE_DATE
, MISSING_VALUES as "SRC_ROWID"
, 1 as "HUB_STATE_IND"
, MISSING_VALUES as ROLE_TP
FROM ECH_ETL_BATCH_ID.Ref_Intermediate
WHERE COLUMN_NM = 'ROLE_TP'
AND LOOKUP_TBL_NM = 'C_S_LU_PTY_ROLE_TP'

You can split the string assignment across lines, which would simplify things a bit as it would reduce (or at the moment, remove) the string concatenation:

l_sql_statement :=
'INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP
(PKEY_SRC_OBJECT, VERSION_SEQ, TIMELINE_ACTION, LAST_UPDATE_DATE,
  SRC_ROWID, HUB_STATE_IND, ROLE_TP)
SELECT MISSING_VALUES AS PKEY_SRC_OBJECT
, 1 as VERSION_SEQ
, 0 as TIMELINE_ACTION
, INSERT_TS as LAST_UPDATE_DATE
, MISSING_VALUES as "SRC_ROWID"
, 1 as "HUB_STATE_IND"
, MISSING_VALUES as ROLE_TP
FROM ECH_ETL_BATCH_ID.Ref_Intermediate
WHERE COLUMN_NM = ''ROLE_TP''
AND LOOKUP_TBL_NM = ''C_S_LU_PTY_ROLE_TP''';

or you could use the alternative quoting mechanism to avoid having to escape the single quotes.

When creating a dynamic statement, start with a valid static one and work backwards; and use dbms_output to display the final generated string so you can verify it and if necessary run it manually.

Of course, this doesn't need to be dynamic at all, but from your original question you intend to use the procedure arguments in a subquery at some point.


To use procedure parameters instead of the string literals you had to start with, you can concatenate those in:

l_sql_statement :=
'INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP
(PKEY_SRC_OBJECT, VERSION_SEQ, TIMELINE_ACTION, LAST_UPDATE_DATE,
  SRC_ROWID, HUB_STATE_IND, ROLE_TP)
SELECT MISSING_VALUES AS PKEY_SRC_OBJECT
, 1 as VERSION_SEQ
, 0 as TIMELINE_ACTION
, INSERT_TS as LAST_UPDATE_DATE
, MISSING_VALUES as "SRC_ROWID"
, 1 as "HUB_STATE_IND"
, MISSING_VALUES as ROLE_TP
FROM ECH_ETL_BATCH_ID.Ref_Intermediate
WHERE COLUMN_NM = ' || P_COLUMN_NAME || '
AND LOOKUP_TBL_NM = ' || P_TARGET_TABLE;

or preferably use bind variables:

l_sql_statement :=
'INSERT INTO ECH_ETL_BATCH_ID.C_S_LU_PTY_ROLE_TP
(PKEY_SRC_OBJECT, VERSION_SEQ, TIMELINE_ACTION, LAST_UPDATE_DATE,
  SRC_ROWID, HUB_STATE_IND, ROLE_TP)
SELECT MISSING_VALUES AS PKEY_SRC_OBJECT
, 1 as VERSION_SEQ
, 0 as TIMELINE_ACTION
, INSERT_TS as LAST_UPDATE_DATE
, MISSING_VALUES as "SRC_ROWID"
, 1 as "HUB_STATE_IND"
, MISSING_VALUES as ROLE_TP
FROM ECH_ETL_BATCH_ID.Ref_Intermediate
WHERE COLUMN_NM = :COLUMN_NAME
AND LOOKUP_TBL_NM = :TARGET_TABLE';

EXECUTE IMMEDIATE l_sql_statement USING P_COLUMN_NAME, P_TARGET_TABLE;

This still doesn't need to be dynamic though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM