Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Exportar datos de consulta sql a archivo(cualquier formato) desde un trigger

3,211 views
Skip to first unread message

tulka...@hotmail.com

unread,
Sep 8, 2008, 8:24:46 AM9/8/08
to
Hola a todos, tengo un pequeño problemita al que no le encuentro
solución, aquí he visto que hay gente que sabe mucho asi que espero
puedan ayudarme. Tengo la necesidad de exportar el resultado de una
consulta simple a un archivo desde un trigger, es esto posible?
Probe exportando a txt y xls con bulk copy y openrowset pero cuando
ejecuto esto desde el trigger, este queda ejecutando eternamente,
curiosamente, fuera del trigger anda bien. Porque me sucede esto? Como
puedo hacer que funcione? Que otras alternativas me sugieren? Necesito
exportar los datos cuando me modifican una tabla, en tiempo real.
Muchas gracias por tomarse el tiempo de leer.
Saludos.

Rubén Garrigós

unread,
Sep 8, 2008, 10:24:01 AM9/8/08
to
¿Podrías darnos más datos? Por ejemplo los scripts de las tablas
involucradas, el trigger que diseñaste y la consulta que deseas exportar
cuando tengas cambios. En principio parece un problema de bloqueo de la
consulta que intentas exportar con el propio trigger que está realizando el
update sobre alguna de las tablas que incluyes en la consulta.

Rubén Garrigós
Solid Quality Mentors

tulka...@hotmail.com

unread,
Sep 8, 2008, 10:44:55 AM9/8/08
to
Los triggers que probe son estos, con ejemplos de northwind.
A TXT:
"create trigger MonitorCustomers
on Customers after update, insert, delete
as

declare @ComandoBCP varchar(100)

set @ComandoBCP = 'bcp "SELECT * FROM Northwind..Categories" queryout
"c:\PruebaMonitor\authors.txt" -T -c'

exec master..xp_cmdshell @comandoBCP, no_output"

A XLS:
"create trigger Prueba on Categories
after update
as

INSERT INTO OPENROWSET ('Microsoft.Jet.OLEDB.4.0', 'Excel
8.0;Database=c:\contact.xls;',
'SELECT * FROM [Hoja1$]')
SELECT TOP 5 customerid,companyname
FROM Customers
GO"

a XML

"create trigger TriggerXML on Customers
for insert
as

declare @outputfile nvarchar(100),
@query nvarchar(100),
@templatefile nvarchar(100)

exec sp_makewebtask @outputfile = 'c:\myxmlfile.xml',
@query = 'select top 5 * from Customer"


La consulta la hice sobre tablas diferentes a las que disparan los
eventos del trigger, para evitar bloqueos, pero sigue sin andar. Vos
sabes bien si es posible ejecutar este tipo de consultas directamente
desde un trigger? Porque eso es crítico para la aplicación que tengo
que desarrollar.
Muchas gracias por tomarte el tiempo de responder.

Rubén Garrigós

unread,
Sep 8, 2008, 11:31:02 AM9/8/08
to
Hola de nuevo,

En principio al primer trigger con bcp que comentas no le encuentro ningún
problema como para que no funcione. ¿Has probado de ejecutar las sentencias
del trigger a mano? Debería volcarte la tabla sin problema. Si no lo hace,
puede que sea un tema de permisos en esa carpeta pues en principio lo veo
todo bien. Prueba también a quitar el "no output" para ver si te devuelve
algún error más inteligible el bcp.

En todo caso, ten en cuenta que lanzar una consulta no dispara ningún
trigger. Únicamente cuando realices alguna modificación sobre la tabla
customers obtendrás el volcado de las categorías de northwind.

En el caso que te comentaba que el volcado afectara a alguna de las tablas
sobre las que actúa el trigger el problema de bloqueo que puedas tener lo
puedes aliviar (aunque no me guste mucho) añadiendo lectura sucia a tu
consulta (nolock).

Rubén Garrigós
Solid Quality Mentors

tulka...@hotmail.com

unread,
Sep 8, 2008, 12:02:42 PM9/8/08
to
Bueno, en realidad había escrito mal la consulta, el bcp me esta
andando bien si no referencio las tablas que usa el trigger...
Entonces asumo que es un problema de bloqueos, te pido disculpas, yo
necesito recuperar las filas modificadas(insertadas, actualizadas o
eliminadas) y enviarlas al archivo txt. Así es la consulta de ejemplo
que uso:

"create trigger MonitorCustomers
on Customers after update, insert, delete
as

select * into tempinserted from inserted
declare @ComandoBCP varchar(100)

set @ComandoBCP = 'bcp "SELECT * FROM Northwind..tempinserted"
queryout "c:\authors.txt" -T -c'

exec master..xp_cmdshell @comandoBCP"

Si yo ejecuto, por ejemplo:

"insert into Customers (customerid, companyname)
values('pepee','aaaaaaaa')"

Al usar tempinserted en la consulta BCP ejecuta eternamente, si por
ejemplo pongo products, que no la usa el trigger, si me exporta bien
los datos y el trigger finaliza sin errores, será porque el trigger
tiene un bloqueo sobre tempinserted? Como hago para esquivarlo? Leí
sobre el read uncomitted pero no se bien donde aplicarlo.
Muchisimas gracias de nuevo.

tulka...@hotmail.com

unread,
Sep 8, 2008, 12:09:11 PM9/8/08
to
Me olvide de preguntarte, es posible obligar al trigger a que no tenga
ningún bloqueo SOLAMENTE sobre tempinserted? Es decir, que bloquee los
recursos que usa excepto tempinserted.

Rubén Garrigós

unread,
Sep 8, 2008, 1:16:21 PM9/8/08
to
Hola de nuevo,

La implementación que comentas tiene el inconveniente de estar utilizando
una tabla que creas con un SELECT INTO lo cual te dará problemas en la
segunda ejecución al existir ya la tabla. Además, no es posible que lo hagas
de esta forma si luego vas a tener un BCP al tener ya una operación bulk como
SELECT INTO.

La solución a esto pasa por crearte una tabla de cambios para cada tabla que
quieras monitorizar previamente (a mano o con un select * into
customers_cambio from customers where 1=2). Esta tabla tendrá las mismas
columnas que la tabla original (en este caso customers). En el cuerpo del
trigger tendrías que sustituir el SELECT INTO por:

DELETE customers_cambios

INSERT customers_cambios
SELECT * FROM inserted

INSISTO, NO me gusta nada esta solución pues además de graves problemas de
rendimiento tiene problemas de concurrencia, de machaque del fichero ante
varios cambios, etc.

Creo que deberías replantearte seriamente lo de insertar en ficheros en el
mismo trigger. Podrías tener una solución mucho más elegante creandote tablas
para auditoria y utilizar el trigger para irlas rellenando con datos.
Periodicamente podrías volcarlas a disco si lo deseas también pero no
directamente en el trigger como pretendes hacer...

Rubén Garrigós
Solid Quality Mentors
"tulka...@hotmail.com" wrote:

tulka...@hotmail.com

unread,
Sep 8, 2008, 1:50:38 PM9/8/08
to
La verdad a mi tampoco me gusta esta solución, me sería mucho mas
facil operar sobre una aplicación cliente, incluso hacer un job que
recorre la tabla de cambios en forma recurrente y exporte el archivo,
pero yo solamente puedo hacer lo que me piden, y me piden esto. Probé
sustituir el select into por una inserción normal pero el bloqueo
sigue, te muestro:

"create trigger MonitorCustomers
on Customers after update, insert, delete
as

delete tabla_cambios

insert tabla_cambios
select customerid,companyname from inserted

declare @ComandoBCP varchar(100)

set @ComandoBCP = 'bcp "SELECT * FROM Northwind..tabla_cambios"


queryout "c:\authors.txt" -T -c'

exec master..xp_cmdshell @comandoBCP"

Cualquier operacion causa que el trigger quede congelado procesando,
se ve que al referenciar tabla_cambios, esta queda bloqueada. Se te
ocurre otra alternativa para ejecutar el bulk copy desde el trigger?
Alguna forma de mantener sin locks tabla_cambios?

Muchas gracias por la ayuda.

Rubén Garrigós

unread,
Sep 8, 2008, 5:32:01 PM9/8/08
to
Hola de nuevo,

Añade el hint (nolock) a la consulta del bcp para permitir que lea datos
sucios, con eso debería funcionarte:

SELECT * FROM Northwind.dbo.tabla_cambios (nolock)

Entiendo que en ocasiones uno se encuentre entre la espada y la pared, pero
es importante, al menos, que los responsables sean consciente que hacer esto
es poco recomendable, propenso a problemas, etc.

Rubén Garrigós

Solid Quality Mentors


> queryout "c:\authors.txt" -T -c'

tulka...@hotmail.com

unread,
Sep 9, 2008, 9:20:49 AM9/9/08
to
Te agradezco mucho por toda la ayuda, esto ya esta andando, un saludo.
0 new messages