【问题标题】:Is there something like "if not exist create sequence ..." in Oracle SQL?Oracle SQL 中是否有类似“如果不存在创建序列...”的内容?
【发布时间】:2010-04-11 18:26:21
【问题描述】:

对于使用 Oracle 8 DB 的应用程序,我提供了一个 SQL 脚本来设置触发器、序列等内容,这些内容可以复制并粘贴到 SQL*Plus 中。如果我尝试创建的序列已经存在,我希望脚本不会因错误而停止。对于触发器,这可以使用“创建或替换触发器...”轻松完成,但对于序列,这不起作用。我也试过 ""if not exists mysequence then create sequence ..." 但它也没有。有其他选择吗?

或者,如果这是不可能的,有没有办法在不存在 SQL*Plus 中止脚本的情况下执行“删除序列 mysequence”?

【问题讨论】:

  • Oracle 中的 AUTOINCREMENT 函数将如何帮助解决源代码控制/配置管理问题?
  • @APC:对不起,我不明白。你能更详细地解释一下吗?我的意思是:我需要的只是一个自动增量字段。在例如SQL Server 我只是将列定义为 autoinc 字段,就完成了。在 Oracle 中,我需要创建一个数字列,然后是一个序列,然后是一个触发器,以使用该序列来填充我的列。这对我来说似乎不是很简单。
  • 我的观点是,如果你有适当的模式管理,你就不需要处理序列的先前存在,因为你只会对你知道该序列的数据库运行 CREATE SEQUENCE 语句不存在。
  • 嗯,我需要为具有不同版本数据库的各种客户以及新客户提供该脚本。我当然可以找出哪个客户有什么架构,并有选择地为他们创建更新脚本,并且还有一个单独的脚本用于初始设置,但为了简单起见,我更喜欢有一个可供所有人使用的单一脚本。让支持部门的同事和在不了解 Oracle 的情况下进行安装的技术人员的工作变得更轻松,对我来说,因为我不需要整理帮助电话,因为有人使用了错误的脚本:-)

标签: sql oracle sequence


【解决方案1】:
DECLARE
  v_dummy NUMBER;
BEGIN
  -- try to find sequence in data dictionary
  SELECT 1
  INTO v_dummy
  FROM user_sequences
  WHERE sequence_name = 'MY_SEQUENCE_NAME';

  -- if sequence found, do nothing
EXCEPTION
  WHEN no_data_found THEN
    -- sequence not found, create it
    EXECUTE IMMEDIATE 'create sequence my_sequence_name';
END;

【讨论】:

  • 我把表名改成了'user_sequences'
【解决方案2】:

如果您确定脚本将始终在 SQL*Plus 下运行,您可以使用指令将 CREATE SEQUENCE 语句括起来以在出错时继续:

WHENEVER SQLERROR CONTINUE
-- create sequences here, ignoring errors
WHENEVER SQLERROR EXIT SQL.SQLCODE

请注意,如果创建序列语句中存在其他错误(权限问题、语法错误等),它们将被忽略

【讨论】:

  • 很好,我不知道那个指令。谢谢!
【解决方案3】:

我喜欢:

DECLARE
  C NUMBER;
BEGIN
  SELECT COUNT(*) INTO C
  FROM ALL_TRIGGERS
  WHERE OWNER = 'YOUROWNER'
  AND TRIGGER_NAME = 'YOURTRIGGER';

  IF (C = 0) THEN
    EXECUTE IMMEDIATE '
      CREATE TRIGGER "YOUROWNER"."YOURTRIGGER"
        blah blah blah your trigger blah blah
    ';
  END IF;
END;
/

【讨论】:

  • 在插入到 MyTable 之前创建或替换触发器 MyTriggerName 更容易使用.....
【解决方案4】:

您可以查看user_sequence表来查看正在创建的序列是否已经存在。

类似于davek的解决方案: 这个想法是,在创建任何序列之前,先删除序列并创建它,全部在动态 SQL 中,创建一个函数,并说当您需要创建 10 个序列时,让函数负责...

function crt_seq(p_seq_name varchar2)
return boolean
begin
   for i in (select 1 from user_sequence where sequence_name = upper(p_seq_name))
   loop
   ---- Already exists. You can drop and recreate or return false to error out
   execute immediate 'drop sequence '||p_seq_name;
   execute immediate 'create sequence '||p_seq_name||' start with 1 increment
                    by 1 nocache';
   end loop;
   return true;
exception
when others then
   return false;
end;

您可以对所有其他选项进行参数化,并拥有一个精心设计的功能来为您创建序列。

【讨论】:

  • 我必须承认我是 Oracle 的新手,我什至不知道在哪里定义该函数以及如何从我的 SQL 脚本中调用它,但是关于 Oracle 的书籍已经在我的办公桌上,所以当我有更多的知识时,你的回答可能会对我有所帮助:-) 谢谢。
  • 警告:如果您有使用该序列的代码(例如包),这将使它们无效。如果在运行此代码时正在使用这些包,您可能还会遇到锁定问题。哦,如果序列已经存在并被使用过,你会得到重复的值。
【解决方案5】:
DECLARE
  lsSeqName VARCHAR2(32 CHAR) := UPPER('MY_SEQUENCE_NAME');
  lnSeqCount NUMBER;
BEGIN
  -- try to find sequence in data dictionary
  SELECT count(1)
    INTO lnSeqCount
    FROM user_sequences
    WHERE UPPER(sequence_name) = lsSeqName;
  -- if sequence not found, create it
  IF lnSeqCount = 0 THEN
    EXECUTE IMMEDIATE 'CREATE SEQUENCE ' || lsSeqName || ' START WITH 1 MINVALUE 1 MAXVALUE 1000000000000000 INCREMENT BY 1 NOCYCLE CACHE 20 NOORDER';
  END IF;
END;
/

-- helper method
PROCEDURE createSeqIfNotExists (
  isSeqName VARCHAR2
) IS
  lnSeqCount NUMBER;
BEGIN
  -- try to find sequence in data dictionary
  SELECT count(1)
    INTO lnSeqCount
    FROM user_sequences
    WHERE UPPER(sequence_name) = UPPER(isSeqName);
  -- if sequence not found, create it
  IF lnSeqCount = 0 THEN
    EXECUTE IMMEDIATE 'CREATE SEQUENCE ' || UPPER(isSeqName) || ' START WITH 1 MINVALUE 1 MAXVALUE 1000000000000000 INCREMENT BY 1 NOCYCLE CACHE 20 NOORDER';
  END IF;
END createSeqIfNotExists;

-- call method
BEGIN
  createSeqIfNotExists('MY_SEQUENCE_NAME');
END;
/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-02
    • 2014-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 2021-05-17
    • 2018-06-07
    相关资源
    最近更新 更多