2011-11-18 22 views
5

Tengo problemas con una consulta sql. Necesito insertar una fila si la misma fila ya no existe. Esto es lo que tengo hasta ahora:sql - inserte si no existe

DECLARE 
BEGIN 
    FOR FOLDER_ROW IN (SELECT FOLDERID, USERID FROM DATA1.FOLDERS) 
     LOOP      
      IF NOT EXISTS (SELECT * FROM DATA1.FOLDER_USER WHERE FOLDER_ID = FOLDER_ROW.FOLDERID AND USER_ID = FOLDER_ROW.USERID) 
      INSERT INTO DATA1.FOLDER_USER (FOLDER_ID, USER_ID) VALUES (FOLDER_ROW.FOLDERID, FOLDER_ROW.USERID); 
    END LOOP; 
    COMMIT; 
END; 

yo no estaría muy familiarizado con SQL en particular el no existe la sintaxis de modo que cuando ejecuto me sale el siguiente error:

ORA-06550: line 37, column 11: PLS-00103: Encountered the symbol "INSERT" when expecting one of the following:

then and or

El símbolo "y luego" fue sustituido por "INSERT" para continuar.

ORA-06550: line 38, column 10: 
PLS-00103: Encountered the symbol "LOOP" when expecting one of the following: 

    if 
ORA-06550: line 40, column 5: 
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: 

    end not pragma final instantiable order overriding static 
    member constructor map 

Respuesta

12

hacerlo todo en SQL en lugar de cambio de contexto en PL/SQL: (? Oracle específica)

INSERT INTO DATA1.FOLDERS 
(folder_id, 
user_id) 
SELECT f1.folder_id, 
     f1.user_id 
    FROM DATA1.FOLDERS f1 
WHERE NOT EXISTS (SELECT 1 
        FROM DATA1.FOLDERS f2 
        WHERE f1.folder_id = f2.folder_id 
         AND f1.user_id = f2.user_id); 
+1

++ 1 'IF EXISTS() ... INSERT' normalmente no es atómico, lo que significa que se podría insertar un registro conflictivo entre el control de existencia y el inserto. –

+0

@M_M: una declaración de SQL en Oracle siempre es atómica. Si no hay un índice único, puede terminar con conflictos porque otra sesión insertada no vio la fila porque la primera sesión aún no la había comprometido. –

+0

No puedo hablar sobre el comportamiento de Oracle aquí, pero tomaré su palabra al respecto. Sé que algunos DBMS tratan 'IF EXISTS (...) THEN' y' INSERT INTO' como dos declaraciones, no una, sino que también depende de los niveles de aislamiento de la transacción y similares. –

1

se le olvidó la ENTONCES

IF condition THEN 
    ... 
ELSE 
    ... 
END IF; 
2

Una mejor solución puede ser la declaración MERGE.

Ver aquí para una buena explicación, con ejemplos:

http://www.oracle-base.com/articles/10g/MergeEnhancements10g.php

Espero que ayude.

+1

'MERGE' no es específico de Oracle. En realidad, es parte de 'SQL: 2008'. Por ejemplo, [DB2] (http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/topic/com.ibm.db2.luw.sql.ref.doc/doc/r0010873.html) (al menos desde v9 para z/OS y 9.5 para LUW) y [SQL Server] (http://technet.microsoft.com/en-us/library/bb510625.aspx), desde 2008. – bhamby

+0

Gracias galador, soy bonita en gran medida exclusivamente un tipo de Oracle, por lo que no estaba seguro de si MERGE era el estándar SQL o la extensión de Oracle. Gracias por la aclaración. –

0
DECLARE 
    N_COUNTS NUMBER; 
BEGIN 
    select count(ID) into N_COUNTS from TABLE_NAME where ID = 1; 
    IF N_COUNTS=0 THEN 
     INSERT QUERY.... 
    ELSE 
     UPDATE QUERY.... 
    END IF; 
END; 
Cuestiones relacionadas