1

I am using the following statement:

query_str='SELECT :NEW.FIRST_NAME||:NEW.LAST_NAME INTO  HostID 
FROM INPUT_TABLE WHERE INPUT_ID='

The trigger has the following code:

EXECUTE IMMEDIATE query_str ||:NEW.INPUT_ID;

I'm getting the following error when updating INPUT_TABLE: ORA-01008: not all variables bound

If I'm updating a record where input_id=111, I would think Oracle would just execute the following statement:

SELECT :NEW.FIRST_NAME||:NEW.LAST_NAME INTO  HostID 
FROM INPUT_TABLE WHERE INPUT_ID=111

Why is it having binding issues?

I'm using SQLDeveloper.

create or replace   
TRIGGER DATA_DETAIL_TRIG
AFTER INSERT OR UPDATE
ON INPUT_TABLE
FOR EACH ROW
 DECLARE
   DATA_SOURCE_ID_RET  NUMBER;
   resultcount        NUMBER;
   query_str          VARCHAR2(512);
   using_cl          VARCHAR2(512);
   HostId      VARCHAR2(256);
   DATA_SOURCE_ID       NUMBER;
   INPUT_ID         NUMBER(38,0);
   AUTOGENERATE_IND       VARCHAR2(1);
   autogen_const varchar(200);
   pragma autonomous_transaction;
   CURSOR C_DATA_SOURCES IS 
    SELECT DATA_SOURCE_ID
    FROM DATA_SOURCE_DETAIL
    WHERE AUTOGENERATE_IND='Y'
    AND DATA_SOURCE_REF.ACTIVE_IND='Y';
BEGIN


OPEN C_DATA_SOURCES;
LOOP
  FETCH C_DATA_SOURCES INTO DATA_SOURCE_ID_RET;
  EXIT WHEN C_DATA_SOURCES%NOTFOUND;
    query_str:=getHostQuery( DATA_SOURCE_ID_RET);
--SELECT :FIRST_NAME||:LAST_NAME||to_char(:DOB,'yyyy/mm/dd')    
From INPUT_TABLE WHERE     INPUT_ID=:INPUT_ID
using_cl:=getHostUsing(DATA_SOURCE_ID_RET);
--:NEW.FIRST_NAME, :NEW.LAST_NAME, :NEW.DOB, :NEW.INPUT_ID
EXECUTE IMMEDIATE query_str  INTO HostId USING using_cl;

  IF INSERTING THEN
    INSERT INTO DETAIL_TABLE
  (
  DETAIL_ID,
  INPUT_ID,
  HOST_ID,
  DATA_SOURCE_ID,
  NOTE,
  DATE_MODIFIED
  ) VALUES
  (
   DETAIL_SEQ.NEXTVAL,
    :NEW.INPUT_ID,
    HostId,
    DATA_SOURCE_ID_RET,
    'Autogenerate Data Source Insert for Insert Input',
    SYSDATE
  );

ELSIF UPDATING THEN



SELECT COUNT(DATA_SOURCE_ID) INTO resultcount FROM DETAIL_TABLE WHERE     
INPUT_ID=:NEW.INPUT_ID AND DATA_SOURCE_ID=DATA_SOURCE_ID_RET;
  IF resultcount>0 THEN


    UPDATE DETAIL_TABLE
    SET
  HOST_ID = HostId,
  NOTE ='Autogenerate Data Source Update for Update Input',
  DATE_MODIFIED =SYSDATE
  WHERE INPUT_ID=:NEW.INPUT_ID
  AND DATA_SOURCE_ID=DATA_SOURCE_ID_RET;


  ELSE
      INSERT INTO DETAIL_TABLE
  (
  DETAIL_ID,
  INPUT_ID,
  HOST_ID,
  DATA_SOURCE_ID,
  NOTE,
  DATE_MODIFIED
  ) VALUES
  (
  DETAIL_SEQ.NEXTVAL,
  :NEW.INPUT_ID,
  HostId,
   DATA_SOURCE_ID_RET,
   'Autogenerate Data Source Insert for Update Input ',

    SYSDATE
  );
END IF;
--end if insert or update inside update

END IF;
--end IF UPDATING
END LOOP;
Close C_DATA_SOURCES;

COMMIT;
END DATA_DETAIL_TRIG;
--end trigger
4

2 回答 2

3

一旦您将:new变量放在引号中,Oracle 就会失去它们作为特殊触发变量的含义,并将它们解释为常规绑定变量。您可能需要USING在动态 sql 中使用子句。就像是

query_str:='SELECT :FIRST_NAME||:LAST_NAME
 FROM INPUT_TABLE WHERE INPUT_ID=:ID';
EXECUTE IMMEDIATE query_str INTO HostID USING 
  :NEW.FIRST_NAME,:NEW.LAST_NAME,:NEW.INPUT_ID;

更新。

现在随着更多细节的出现,我想知道你为什么需要查询?据我所知,您只需HostIDINPUT_TABLE. 但是由于您已经将触发器附加到同一个表,因此您已经拥有所需的所有值并且可以简单地执行

HostID := :NEW.FIRST_NAME||:NEW.LAST_NAME;

只有当您查询不同的表时,您的方法才有意义。在这种情况下,正如我所提到的,您不能引用:NEW:OLD将它们放在USING. 不过,您可以从它们中组合其他价值。

于 2012-07-03T21:22:48.403 回答
0

@Alex:下面是触发器。

create or replace   
TRIGGER DATA_DETAIL_TRIG
AFTER INSERT OR UPDATE
ON INPUT_TABLE
FOR EACH ROW
 DECLARE
   DATA_SOURCE_ID_RET  NUMBER;
   resultcount        NUMBER;
   query_str          VARCHAR2(512);
   using_cl          VARCHAR2(512);
   HostId      VARCHAR2(256);
   DATA_SOURCE_ID       NUMBER;
   INPUT_ID         NUMBER(38,0);
   AUTOGENERATE_IND       VARCHAR2(1);
   autogen_const varchar(200);
   pragma autonomous_transaction;
   CURSOR C_DATA_SOURCES IS 
    SELECT DATA_SOURCE_ID
    FROM DATA_SOURCE_DETAIL
    WHERE AUTOGENERATE_IND='Y'
    AND DATA_SOURCE_REF.ACTIVE_IND='Y';
BEGIN


OPEN C_DATA_SOURCES;
LOOP
  FETCH C_DATA_SOURCES INTO DATA_SOURCE_ID_RET;
  EXIT WHEN C_DATA_SOURCES%NOTFOUND;
    query_str:=getHostQuery( DATA_SOURCE_ID_RET);
--SELECT :FIRST_NAME||:LAST_NAME||to_char(:DOB,'yyyy/mm/dd')    
From INPUT_TABLE WHERE     INPUT_ID=:INPUT_ID
using_cl:=getHostUsing(DATA_SOURCE_ID_RET);
--:NEW.FIRST_NAME, :NEW.LAST_NAME, :NEW.DOB, :NEW.INPUT_ID
EXECUTE IMMEDIATE query_str  INTO HostId USING using_cl;

  IF INSERTING THEN
    INSERT INTO DETAIL_TABLE
  (
  DETAIL_ID,
  INPUT_ID,
  HOST_ID,
  DATA_SOURCE_ID,
  NOTE,
  DATE_MODIFIED
  ) VALUES
  (
   DETAIL_SEQ.NEXTVAL,
    :NEW.INPUT_ID,
    HostId,
    DATA_SOURCE_ID_RET,
    'Autogenerate Data Source Insert for Insert Input',
    SYSDATE
  );

ELSIF UPDATING THEN



SELECT COUNT(DATA_SOURCE_ID) INTO resultcount FROM DETAIL_TABLE WHERE     
INPUT_ID=:NEW.INPUT_ID AND DATA_SOURCE_ID=DATA_SOURCE_ID_RET;
  IF resultcount>0 THEN


    UPDATE DETAIL_TABLE
    SET
  HOST_ID = HostId,
  NOTE ='Autogenerate Data Source Update for Update Input',
  DATE_MODIFIED =SYSDATE
  WHERE INPUT_ID=:NEW.INPUT_ID
  AND DATA_SOURCE_ID=DATA_SOURCE_ID_RET;


  ELSE
      INSERT INTO DETAIL_TABLE
  (
  DETAIL_ID,
  INPUT_ID,
  HOST_ID,
  DATA_SOURCE_ID,
  NOTE,
  DATE_MODIFIED
  ) VALUES
  (
  DETAIL_SEQ.NEXTVAL,
  :NEW.INPUT_ID,
  HostId,
   DATA_SOURCE_ID_RET,
   'Autogenerate Data Source Insert for Update Input ',

    SYSDATE
  );
END IF;
--end if insert or update inside update

END IF;
--end IF UPDATING
END LOOP;
Close C_DATA_SOURCES;

COMMIT;
END DATA_DETAIL_TRIG;
--end trigger
于 2012-07-06T21:58:25.390 回答