【问题标题】:How to check if a column exists before adding it to an existing table in PL/SQL?如何在将列添加到 PL/SQL 中的现有表之前检查列是否存在?
【发布时间】:2011-09-15 03:51:45
【问题描述】:

如何在向 oracle 数据库的表中添加列之前添加一个简单的检查?我已包含用于添加列的 SQL。

ALTER TABLE db.tablename 
  ADD columnname NVARCHAR2(30);

【问题讨论】:

    标签: sql oracle plsql


    【解决方案1】:

    检查列是否存在

    select column_name as found
    from user_tab_cols
    where table_name = '__TABLE_NAME__'
    and column_name = '__COLUMN_NAME__'
    

    Reference link

    【讨论】:

    • 这个答案只是复制了其他答案中给出的建议,没有添加任何内容。
    【解决方案2】:

    可以使用以下视图之一访问有关 Oracle 数据库中列的所有元数据。

    user_tab_cols; -- 对于用户拥有的所有表

    all_tab_cols ; -- 对于用户可以访问的所有表

    dba_tab_cols; -- 对于数据库中的所有表。

    因此,如果您在 SCOTT.EMP 表中查找类似 ADD_TMS 的列,并且仅在该列不存在时才添加该列,PL/SQL 代码将遵循这些行..

    DECLARE
      v_column_exists number := 0;  
    BEGIN
      Select count(*) into v_column_exists
        from user_tab_cols
        where upper(column_name) = 'ADD_TMS'
          and upper(table_name) = 'EMP';
          --and owner = 'SCOTT --*might be required if you are using all/dba views
    
      if (v_column_exists = 0) then
          execute immediate 'alter table emp add (ADD_TMS date)';
      end if;
    end;
    /
    

    如果您打算将此作为脚本运行(不是过程的一部分),最简单的方法是在脚本中包含 alter 命令并在脚本末尾查看错误,假设您没有 Begin -脚本结束..

    如果你有 file1.sql

    alter table t1 add col1 date;
    alter table t1 add col2 date;
    alter table t1 add col3 date;
    

    并且 col2 存在,当脚本运行时,其他两列将添加到表中,并且日志将显示错误“col2”已经存在,所以你应该没问题。

    【讨论】:

    • @Mesa 非常真实
    • column_nametable_name 中的比较字符串总是需要大写(这就是@mastaBlasta 写他的评论的原因),即使你用不同的大小写创建它们。 create table foo (bar number); 将导致 table_name=FOOcolumn_name='BAR'
    • @bugybunny 除非列名和表名实际上是用小写字母创建的。 create table "foo" ("bar" number);。请注意,这意味着您可以拥有名为FOOFooFOo 的表。所以下面的 groksters 解决方案更好地解决了这个问题。
    【解决方案3】:

    通常,我建议尝试使用 ANSI-92 标准元表来处理类似的问题,但我现在看到 Oracle 不支持它。

    -- this works against most any other database
    SELECT
        * 
    FROM 
        INFORMATION_SCHEMA.COLUMNS C 
        INNER JOIN 
            INFORMATION_SCHEMA.TABLES T 
            ON T.TABLE_NAME = C.TABLE_NAME 
    WHERE 
        C.COLUMN_NAME = 'columnname'
        AND T.TABLE_NAME = 'tablename'
    

    相反,looks 就像你需要做类似的事情

    -- Oracle specific table/column query
    SELECT
        * 
    FROM
        ALL_TAB_COLUMNS 
    WHERE
        TABLE_NAME = 'tablename'
        AND COLUMN_NAME = 'columnname'
    

    抱歉,我没有 Oracle 实例来验证上述内容。如果它不起作用,请告诉我,我将删除此帖子。

    【讨论】:

    • 或尝试并捕获异常
    • 如果您查询ALL_TAB_COLUMNS 数据字典视图,您需要在OWNER 列上包含一个谓词,以防同一个表存在于多个模式中。如果您知道您只对当前用户架构中的表感兴趣,则应该改用USER_TAB_COLUMNS 视图。
    • Errrr 在第一个 sn-p 中你的意思是写“COLUMN_NAME”(而不是“COLLATION_NAME”)
    • 感谢@xDisruptor 我现在已经更正了它
    【解决方案4】:

    或者,您可以忽略错误:

    declare
        column_exists exception;
        pragma exception_init (column_exists , -01430);
    begin
        execute immediate 'ALTER TABLE db.tablename ADD columnname NVARCHAR2(30)';
        exception when column_exists then null;
    end;
    /
    

    【讨论】:

    • 漂亮干净。谢谢!
    • 甜蜜!这也可以用于 table_exists 吗?
    • 很遗憾,没有“table_exists”。
    • @grokster 要检查表是否存在,只需使用代码 -955 而不是 -01430
    • 工作完美,非常适合避免讨厌的 maven flyway 错误
    猜你喜欢
    • 1970-01-01
    • 2012-03-22
    • 2018-03-24
    • 1970-01-01
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 2021-04-04
    • 1970-01-01
    相关资源
    最近更新 更多