2009-06-29 12 views
9

Estoy tratando de escribir un desencadenador para sqlite y simplemente me encuentro con todo tipo de problemas. En verdad, creo que mi verdadero problema es mi pobre historial en el lenguaje sql. De todos modos aquí va ...Crear un desencadenador de SQL condicional en SQLite

Tengo dos tablas Table1 y Table2. Table1 tiene una columna llamada time (que es un tiempo entero de 64 bits). Necesito un disparador que mira para insertar una nueva fila en Table1. Si hay 3 o más filas en la Tabla 1 que tienen un tiempo mayor que X (un valor codificado en el siguiente ejemplo 120 segundos), necesito insertar una nueva fila en la Tabla 2.

Esto es lo que tengo hasta ahora (Nota esto no funciona)

CREATE TRIGGER testtrigger AFTER 
INSERT ON Table1 WHEN 
( 
    SELECT COUNT() AS tCount FROM 
    ( 
    SELECT * FROM Table1 WHERE 
     time > (NEW.time - 120) 
    ) WHERE tCount > 3 
) 
BEGIN 
    INSERT INTO Table2 (time, data) VALUES 
    (NEW.time, 'data1'); 
END 

cualquier tipo almas por ahí que son mejores en SQL que yo?

Respuesta

8

Esto funciona porque la cláusula WHEN necesita un expression:

sqlite> .schema Table1 
CREATE TABLE Table1 (time int); 
CREATE TRIGGER testtrigger AFTER INSERT ON Table1 
WHEN 3<(SELECT Count() FROM Table1 WHERE time>(NEW.time-120)) 
BEGIN 
INSERT INTO Table2 (time, data) VALUES (NEW.time,'data1'); 
END; 

¿Has mirado en este reference page? Por lo que puedo decir, este es un "mal uso de agregado" que probablemente proviene de la declaración en la sección When. Tenías esto:

sqlite> .tables 
Table1 Table2 
sqlite> .schema Table1 
CREATE TABLE Table1 (time int); 
CREATE TRIGGER testtrigger AFTER 
INSERT ON Table1 WHEN 
( 
    SELECT COUNT() AS tCount FROM 
    ( 
    SELECT * FROM Table1 WHERE 
     time > (NEW.time - 120) 
    ) WHERE tCount > 3 
) 
BEGIN 
    INSERT INTO Table2 (time, data) VALUES 
    (NEW.time, 'data1'); 
END; 
sqlite> .schema Table2 
CREATE TABLE Table2 (time int,data string); 
sqlite> insert into Table1 VALUES (5); 
SQL error: misuse of aggregate: 
sqlite> 

Intenté borrar "WHERE tCount" para convertirlo en un expression, pero entonces tiene un error de sintaxis en el operador.

Así que, en cambio, cambié las cosas por la solución anterior.

+0

El enlace no funciona y sí, se me ha prestado mucha atención a la referencia de lenguaje sql en el sitio web de sqlite. Simplemente no estoy recibiendo "eso". –

+0

Sí, StackOverflow tiene un problema con mi enlace, debería ser: http://sqlite.org/lang_createtrigger.html; cambie el% 5f a a '_' – dlamblin

+0

@Typhoid - Creo que la cláusula WHEN activada espera una expresión de comparación que devuelve verdadero o falso, en lugar de devolver un número. Entonces, el segundo formato debería funcionar. No está claro en el diagrama de sintaxis de SQLite para expr que necesite tener algo que devuelva verdadero/falso en este caso, por lo que tiene sentido que le resulte confuso. SQLite está bien documentado, pero todavía tiene lagunas. Enviaría un correo electrónico al equipo de SQLite y mencionaría esto. –

-5

¿Quizás un enfoque sintáctico diferente?

CREATE TRIGGER testtrigger ON Table1 

FOR INSERT 
AS 
BEGIN 

    DECLARE @timeNum int 

    SET @timeNum = SELECT count(*) FROM Table1 WHERE time > (New.time - 120) 

    IF @timeNum > 3 

    BEGIN 
     INSERT INTO Table2 (time, data) VALUES 
      (NEW.time, 'data1'); 
    END 

END 

Pero también, intente algunas declaraciones de depuración. Cuando estaba depurando mi último disparador para un servicio web, coloqué algunas instrucciones INSERT en una tabla de depuración que configuré. Por lo tanto, podría generar el @timeNum cada vez que se llame al desencadenador, y luego colocar otro INSERT de depuración dentro del ciclo para ver si realmente entra en la lógica de INSERT de Table2.

ACTUALIZACIÓN: ¡Lo siento! Parece que SqlLite es una mierda, no sabía que carecía de esta sintaxis. Sin embargo, si no obtiene ninguna respuesta, considere algunas declaraciones de depuración para asegurarse de que las rutas de su código se llamen en las condiciones adecuadas.

+1

No creo que pueda usar DECLARE, SET o IF en sqlite – dlamblin

+3

Su código es T-SQL, no SQLite. SQLite carece de construcciones de lenguaje de procedimiento. –

1

Su cláusula WHEN en el activador debe ser una expresión de comparación que devuelve verdadero o falso, en lugar de devolver un número. Prueba la idea de dlamblin.

Cuestiones relacionadas