none
Replicar insert de una instancia a otra con Triggers RRS feed

  • Pregunta

  • Hola a todos,

    Estoy intentando replicar un insert que me viene a un servidor, en otro servidor, para tener las tablas de ambos servidores sincronizadas.

    Muchos me van a decir que use Replicación Transaccional, hemos investigado esa posibilidad y actualmente no es viable con la versión que disponemos de SQL Server (Web Edition).

    He pensado que para solventar este problema, lo más indicado sería un trigger que salte cada vez que que hace un insert en una tabla, y que haga que se haga un insert al otro servidor, que contiene una tabla con la misma estructura.

    El trigger lo he creado de tal forma que seleccione todas las columnas de las tablas excepto la clave primaria (por que es autoincrement y me devuelve un error si intento insertar datos en esa columna), y hacer un insert into [servidor].[basedatos].[dbo].[tabla] (campos insert) from inserted

    Mi problema es que esta sql es dinamica, y no he conseguido acceder a la tabla inserted desde execute(@sQL), me dice El nombre de objeto 'inserted' no es válido.

    Para probar esto, tienes que tener dos instancias, y que esten linkadas.

    En cada una de las instancias hay que crear una base de datos llamada Pruebas y una tabla a esta base de datos llamada prueba1.

    A su vez, la tabla prueba1 tiene los campos (id, que es clave primaria) y (valor) que es un entero)

    CREATE TRIGGER pruebaTrigger1 on dbo.prueba1
    FOR INSERT
    AS
    declare @nombrestabla nvarchar(400)
    declare @stringnombreTablas nvarchar(4000)
    declare @SQLinsert nvarchar(4000)
    DECLARE NOMBRES_TABLAS CURSOR FOR
    select COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'prueba1'
    OPEN NOMBRES_TABLAS
    set @stringnombreTablas = ''
    FETCH NEXT FROM NOMBRES_TABLAS INTO @nombrestabla
    WHILE @@FETCH_STATUS =0
    BEGIN
    	IF @nombrestabla <> 'id'
    	SET @stringnombreTablas = @stringnombreTablas+', '+ @nombrestabla
    	FETCH NEXT FROM NOMBRES_TABLAS INTO @nombrestabla
    END
    CLOSE NOMBRES_TABLAS
    DEALLOCATE NOMBRES_TABLAS
    set @stringnombreTablas = SUBSTRING(@stringnombreTablas, 3, LEN(@stringnombreTablas)-1)
    print @stringnombreTablas
    --set @SQLinsert = 'insert into [SERV26-PC\INSPEDRO].[Pruebas].[dbo].[prueba1] ('+@stringnombreTablas+') select '+@stringnombreTablas+'  FROM inserted'
    set @SQLinsert = 'select * into [SERV26-PC\INSPEDRO].[Pruebas].[dbo].[prueba1] FROM inserted'
    print @SQLinsert
    EXECUTE(@SQLinsert)

    Aqui dejo la SQL del trigger.

    jueves, 6 de abril de 2017 10:37

Respuestas

  • Brayan De La Cruz,

    No estoy de acuerdo con tu comentario.

    La razon es que el alcance de esas tablas virtuales es dentro del disparador y dentro de la misma transaccion.

    Al usar sql dinamico el codigo se ejecuta fuera de ese alcance, lo mismo pasa con variables pues estas estarian fuera del alcance.

    Una forma seria insertar en una tabla fija o temporal para poder ser accesada, pero creo deberias buscar otras soluciones ya que puedes imaginar lo que pasaria si haces un insert en masa y no apagas el trigger, quizas log shipping o database mirror que si estan presentes en la editicion WEB.

    Ejemplo:

    CREATE TABLE dbo.T1 (col1 int);
    GO
    CREATE TRIGGER tr_ins_T1 ON dbo.T1 FOR INSERT
    AS
    CREATE TABLE #T (col1 int);
    
    INSERT INTO #T (col1)
    SELECT col1 FROM Inserted;
    
    EXEC ('SELECT * FROM #T;');
    GO
    INSERT INTO dbo.T1 (col1)
    VALUES (1), (2), (3);
    GO
    DROP TRIGGER tr_ins_T1;
    GO
    DROP TABLE dbo.T1;
    GO


    AMB

    Some guidelines for posting questions...

    AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas


    • Editado HunchbackMVP jueves, 6 de abril de 2017 13:10
    • Marcado como respuesta Samael205 jueves, 6 de abril de 2017 14:37
    jueves, 6 de abril de 2017 13:09

Todas las respuestas

  • Hola, Lo que sucede es que en el From no te permite parámetros , por ello el error, y si lo haces mediante un job?

    Si ayudé a resolver tu consulta, no olvides marcar como respuesta y/o votar como útil.

    jueves, 6 de abril de 2017 12:40
  • Brayan De La Cruz,

    No estoy de acuerdo con tu comentario.

    La razon es que el alcance de esas tablas virtuales es dentro del disparador y dentro de la misma transaccion.

    Al usar sql dinamico el codigo se ejecuta fuera de ese alcance, lo mismo pasa con variables pues estas estarian fuera del alcance.

    Una forma seria insertar en una tabla fija o temporal para poder ser accesada, pero creo deberias buscar otras soluciones ya que puedes imaginar lo que pasaria si haces un insert en masa y no apagas el trigger, quizas log shipping o database mirror que si estan presentes en la editicion WEB.

    Ejemplo:

    CREATE TABLE dbo.T1 (col1 int);
    GO
    CREATE TRIGGER tr_ins_T1 ON dbo.T1 FOR INSERT
    AS
    CREATE TABLE #T (col1 int);
    
    INSERT INTO #T (col1)
    SELECT col1 FROM Inserted;
    
    EXEC ('SELECT * FROM #T;');
    GO
    INSERT INTO dbo.T1 (col1)
    VALUES (1), (2), (3);
    GO
    DROP TRIGGER tr_ins_T1;
    GO
    DROP TABLE dbo.T1;
    GO


    AMB

    Some guidelines for posting questions...

    AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas


    • Editado HunchbackMVP jueves, 6 de abril de 2017 13:10
    • Marcado como respuesta Samael205 jueves, 6 de abril de 2017 14:37
    jueves, 6 de abril de 2017 13:09
  • Segun tengo entendido, la caracteristica Mirroring sólo permite una de las bases de datos clonadas que esté en producción y la otra esté en standby. En mi caso hago esto por que tengo que tener las dos instancias funcionando al mismo tiempo, una para que soporte toda de recepción de datos y calculos, y la otra para que los clientes puedan acceder a ella, liberando a la base de datos de los clientes de todo el trabajo que se realiza en la base de datos original.

    Especifico un poco más, podeis llamarme loco, pero no he llegado a otra conclusión... Necesitamos tener dos instancias de bases de datos sincronizadas, y en funcionamiento. Hemos visto todas las soluciones de Alta disponibilidad que ofrece SQL Server, y no podemos acceder a ninguna de estas soluciones, o bien por razones económicas (Enterprise no se puede, elevado costo y Standard no se puede, elevado costo), Solo disponemos de la edición Web.

    La idea es, tenemos muchas bases de datos, y cuando digo muchas son unas 8000 bases de datos, que tienen todas la misma estructura. todas tienen 11 tablas. ¿Seria viable crear mediante un cursor que recorra todas esas bases de datos, y esas 11 tablas por cada base de datos, y que cree tres Trigger (update, delete e insert) para que cuando se apliquen estas instrucciones, se envíen estos datos mediante un insert a otro servidor remoto?. Teniendo en cuenta que muchas de estas bases de datos se realizan inserts cada cuarto de hora.

    • Editado Samael205 jueves, 6 de abril de 2017 14:00 Añadir información
    jueves, 6 de abril de 2017 13:48
  • Hola Hunchback De acuerdo comprendo, pero es recomendable para el performance usar tablas temporales?

    Si ayudé a resolver tu consulta, no olvides marcar como respuesta y/o votar como útil.

    jueves, 6 de abril de 2017 13:57
  • Samael205,

    Que pasaria si el otro servidor se cae por cualquier razon, como lo pondrias al dia?

    Desgraciadamente las razones economicas suelen interponerse en la arquitectura de nuestras aplicaciones.

    Sigue tratando hasta que encuentres algo que les funcione de acuerdo a sus necesidades.


    AMB

    Some guidelines for posting questions...

    AYÚDANOS A AYUDARTE, guía básica de consejos para formular preguntas

    jueves, 6 de abril de 2017 16:15
  • Pasaria que el usuario perderia todos sus datos antes de ese dia, por que las actualizaciones diarias.

    Hemos pensando en hacer también Backups incrementales cuartohorarias y restaurarlas en el servidor de clientes. ¿Como de penalizante sería esta opción?.

    Nuestra actual opción es, realizar una copia de seguridad de la base de datos, diaria, por ejemplo, y guardarla en una carpeta compartida. Mapear esa carpeta en SQL Server, y acceder al .bak y restaurarlo en la bd de clientes, así también podriamos disponer de los datos actualizados constantemente....

    lunes, 10 de abril de 2017 13:57