【问题标题】:Equivalent to IF NOT EXISTS in Oracle?相当于Oracle中的IF NOT EXISTS?
【发布时间】:2017-06-23 14:42:26
【问题描述】:

以下语句在 MSSQL 中有效:

IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_StationObjectsID]') AND parent_object_id = OBJECT_ID(N'[Attendance]'))
BEGIN
    ALTER TABLE Attendance ADD CONSTRAINT FK_StationObjectsID FOREIGN KEY (StationObjectsID) REFERENCES stationobjects (stationobjectsid)
END

我在 Oracle 中尝试过:

IF NOT EXISTS (SELECT * FROM USER_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_STATIONOBJECTSID' AND TABLE_NAME = 'ATTENDANCE') THEN
BEGIN
    ALTER TABLE Attendance ADD CONSTRAINT FK_StationObjectsID FOREIGN KEY (StationObjectsID) REFERENCES stationobjects (stationobjectsid);
END;

但它给了我一个错误 PLS-00103 “遇到符号 'ALTER'...”

【问题讨论】:

  • 试试execute immediate 'alter . . .'
  • 你需要一个带有动态 SQL 的 PL/SQL 块
  • 感谢 GurV,现在收到另一个错误,即外键已经存在。好像IF有什么问题。执行 SELECT 时返回一行,但仍在尝试执行 ALTER ...

标签: oracle exists


【解决方案1】:

使用立即执行在 PLSQL 块中触发 ddl:

IF <condition> THEN 
    Execute immediate 'ALTER TABLE . . .';
END if;

最接近不存在的是Tom Kyte here给出的方法

begin
  for i in (select count(*) cnt from dual 
            where not exists (
                SELECT *
                FROM USER_CONSTRAINTS 
                WHERE CONSTRAINT_NAME = 'FK_STATIONOBJECTSID' 
                AND TABLE_NAME = 'ATTENDANCE'
            )) loop
            if (i.cnt = 1) then
              execute immediate 'ALTER TABLE Attendance ADD CONSTRAINT FK_StationObjectsID FOREIGN KEY (StationObjectsID) REFERENCES stationobjects (stationobjectsid)';
            end if;
  end loop;
end;
/

更简单的方法是:

declare
  n int := 0;
begin
  select count(*) into n
  from user_constraints
  where constraint_name = 'FK_STATIONOBJECTSID'
  and table_name = 'ATTENDANCE';
  if n = 0 then
    execute immediate 'ALTER TABLE Attendance ADD CONSTRAINT FK_StationObjectsID FOREIGN KEY (StationObjectsID) REFERENCES stationobjects (stationobjectsid)';
  end if;
end;
/

看 - https://dba.stackexchange.com/questions/37362/why-cant-we-write-ddl-statement-directly-into-the-pl-sql-block

【讨论】:

    【解决方案2】:

    您可以在 SQL 查询中使用 EXISTS,但不能像您尝试的那样在 PLSQL 条件中使用。

    您可能需要以下内容:

    declare
        vCheck number;
    begin
        select count(1)
        into vCheck
        from user_constraints
        where constraint_name = 'FK_STATIONOBJECTSID'
          and table_name = 'ATTENDANCE';
        --
        if vCheck = 0 then
            execute immediate 'ALTER TABLE Attendance ADD CONSTRAINT FK_StationObjectsID FOREIGN KEY (StationObjectsID) REFERENCES stationobjects (stationobjectsid)';
        end if;
    end;
    

    【讨论】:

      【解决方案3】:

      得到它的工作,但可能不是最好的解决方案:

      DECLARE
        foreign_key_exists number := 0;  
      BEGIN
        SELECT COUNT(*) INTO foreign_key_exists FROM USER_CONSTRAINTS WHERE upper(CONSTRAINT_NAME) = upper('FK_StationObjectsID') AND upper(TABLE_NAME) = upper('Attendance');
        IF (foreign_key_exists = 0) 
          THEN
            EXECUTE IMMEDIATE 'ALTER TABLE Attendance ADD CONSTRAINT FK_StationObjectsID FOREIGN KEY (StationObjectsID) REFERENCES stationobjects (stationobjectsid)';
        END IF;
      END;
      /
      

      【讨论】:

        【解决方案4】:

        如何执行 DDL,并忽略任何“外键已存在”错误。

        不优雅,但不依赖于键名不变。

        【讨论】:

          猜你喜欢
          • 2012-06-05
          • 2020-05-11
          • 1970-01-01
          • 1970-01-01
          • 2012-01-03
          • 1970-01-01
          • 2011-11-15
          • 2021-10-20
          • 2010-11-13
          相关资源
          最近更新 更多