2010-04-11 9 views
16

Para mi aplicación que usa una base de datos Oracle 8, estoy proporcionando una secuencia de comandos SQL para configurar cosas como desencadenantes, secuencias, etc., que se pueden copiar y pegar en SQL * Plus. Me gustaría que el script no se detenga con un error si ya existe una secuencia que intento crear. Para un Disparador, esto se puede hacer fácilmente usando "crear o reemplazar el activador ...", pero para una secuencia, esto no funciona. También probé "" si no existe mysecuencia y luego creo secuencia ... "pero no fue así. ¿Hay alguna alternativa?¿Hay algo así como "si no existe crear secuencia ..." en Oracle SQL?

Alternativamente, si esto no es posible, ¿hay alguna manera de hacer una" secuencia de caída mysecuencia "sin SQL * Plus abortar la secuencia de comandos si mysequence no existe

+0

¿Cómo la presencia de una función de incremento automático en Oracle ayudar a resolver lo que es claramente un problema de gestión de control de fuente/configuración? – APC

+0

@APC: Lo siento, no entiendo. ¿Puedes explicar esto con más detalle? Lo que quise decir es: todo lo que necesito para una mesa es un campo de autoincrement. En, por ejemplo, SQL Server Solo defino que la columna sea un campo autoinc, y he terminado. En Oracle necesito crear una columna numérica, luego una secuencia, luego un disparador para usar esa secuencia para llenar mi columna. Esto no me parece muy directo. – Timo

+0

Mi punto es que si tuviera una gestión de esquema adecuada, no necesitaría manejar la existencia previa de una secuencia porque solo estaría ejecutando una sentencia CREATE SEQUENCE contra bases de datos donde sabía que esa secuencia no existía. – APC

Respuesta

7

Si está seguro de la secuencia de comandos siempre se ejecutará en SQL * Plus, puede soporte de la SECUENCIA declaraciones CREATE con una directiva a seguir en caso de error:

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

Tenga en cuenta si hay otros errores (permiso problemas, fallos de sintaxis, etc.) en los estados de secuencia crear serán ignoradas

+0

Bien, no sabía sobre esa directiva. ¡Gracias! – Timo

1

puede comprobar user_sequence mesa para ver si se está creando la secuencia ya existe o no

similares a davek 's solución:?. la idea es , antes de crear cualquier secuencia, suelta la secuencia y créela, todo en SQL dinámico, crea una función y di cuándo necesitas crear una secuencia de 10, deja que el fu nción cuidar ...

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; 

Puede parametrizar todas las demás opciones y tienen una función compleja para crear la secuencia para usted.

+0

Debo admitir que Soy tan novato con Oracle, ni siquiera sé dónde definir esa función y cómo llamarla desde mi script SQL, pero mis libros sobre Oracle ya están en mi escritorio, por lo que su respuesta probablemente me ayude cuando tenga más conocimiento. :-) Gracias. – Timo

+1

Advertencia: si tiene un código (por ejemplo, paquetes) usando la secuencia, esto los invalidará. También puede tener problemas de bloqueo si esos paquetes están en uso cuando ejecuta este código. Ah, y si la secuencia ya existía y se había utilizado, obtendrás valores duplicados. –

+0

Ok, gracias. – Timo

11
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; 
+1

Buen intento, pero en esta forma, no funcionará. Tiene un problema en mayúscula-minúscula: debe ser WHERE sequence_name = 'MY_SEQUENCE_NAME'; –

+0

@ammoQ Ahora está corregido, gracias. – jva

+0

He alterado el nombre de la tabla para que sea 'user_sequences' – Shawn

4

que me gustan:

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; 
/
+0

Mucho más fácil de usar CREA O REEMPLAZA TRIGGER MyTriggerName ANTES DE INSERTAR EN MyTable ..... – Oscar

0
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; 
/

O

-- 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; 
/
Cuestiones relacionadas