w3schools update trigger example ejemplos create before after sql tsql triggers

update - trigger sql w3schools



T-SQL desencadena la activación de un error de "Nombre de columna o número de valores proporcionados que no coinciden con la definición de tabla" (4)

¿Qué es companies_contactInfo_updateTerritories? La referencia real menciona el procedimiento "companies_contactInfo_updateTerritories" pero no lo veo en el código proporcionado. Además, no veo dónde se llama. A menos que sea de su aplicación que llama al SQL y por lo tanto irrelevante ....

Si probaste todo y funcionó, pero ahora no funciona, entonces algo debe ser diferente. Una cosa a considerar es la seguridad. Noté que solo llamas a la tabla [dandb_raw] y no a [dbo]. [Dandb_raw]. Entonces, si el usuario tuviera una tabla del mismo nombre [usuario]. [Dandb_raw], esa tabla se usaría para verificar las definiciones en lugar de su tabla. Además, el disparador crea tablas temporales. Pero si algunas de las tablas temporales ya existían por cualquier razón pero con diferentes definiciones, esto también puede ser un problema.

Aquí hay algo que no he podido solucionar, y he buscado en todas partes . ¡Quizás alguien aquí lo sepa!

Tengo una tabla llamada dandb_raw, con tres columnas en particular: dunsId (PK), name y searchName. También tengo un disparador que actúa en esta tabla:

SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER TRIGGER [dandb_raw_searchNames] ON [dandb_raw] FOR INSERT, UPDATE AS SET NOCOUNT ON select dunsId, name into #magic from inserted UPDATE dandb SET dandb.searchName = company_generateSearchName(dandb.name) FROM (select dunsId, name from #magic) i INNER JOIN dandb_raw dandb on i.dunsId = dandb.dunsId --Add new search matches SELECT c.companyId, dandb.dunsId INTO #newMatches FROM dandb_raw dandb INNER JOIN (select dunsId, name from #magic) a on a.dunsId = dandb.dunsId INNER JOIN companies c ON dandb.searchName = c.searchBrand --avoid url matches that are potentially wrong AND (lower(dandb.url) = lower(c.url) OR dandb.url = '''' OR c.url = '''' OR c.url is null) INSERT INTO #newMatches (companyId, dunsId) SELECT c.companyId, max(dandb.dunsId) dunsId FROM dandb_raw dandb INNER JOIN ( select case when charindex(''/'',url) <> 0 then left(url, charindex(''/'',url)-1) else url end urlMatch, * from companies ) c ON dandb.url = c.urlMatch where subsidiaryOf = 1 and isReported = 1 and dandb.url <> '''' and c.companyId not in (select companyId from #newMatches) group by companyId having count(dandb.dunsId) = 1 UPDATE cd SET cd.dunsId = nm.dunsId FROM companies_dandb cd INNER JOIN #newMatches nm ON cd.companyId = nm.companyId GO

El desencadenador hace que las inserciones fallen:

insert into [dandb_raw](dunsId, name) select 3442355, ''harper'' union all select 34425355, ''har 466per'' update [dandb_raw] set name =''grap6767e''

Con este error:

Msg 213, Level 16, State 1, Procedure companies_contactInfo_updateTerritories, Line 20 Insert Error: Column name or number of supplied values does not match table definition.

Lo más curioso de esto es que cada una de las declaraciones individuales en el disparador funciona por sí misma. Es casi como si se insertara una tabla única que infecta tablas temporales si intentas moverlas insertadas en una de ellas.

Entonces, ¿qué causa que el gatillo falle? ¿Cómo se puede detener?


Creo que David y Cervo juntos han tratado el problema aquí.

Estoy bastante seguro de que parte de lo que sucedía era que estábamos usando #newMatches en múltiples factores desencadenantes. Cuando un desencadenador cambiaba algunas filas, activaba otro desencadenante, que intentaba utilizar la conexión con el alcance #newMatches.

Como resultado, intentaría encontrar la tabla que ya existía con un esquema diferente, morir y producir el mensaje anterior. Una pieza de evidencia que estaría a favor: ¿El insertado usa un alcance de estilo de pila (los disparadores anidados tienen sus propias inserciones?)

Sin embargo, aún especulaba: ¡al menos las cosas parecen estar funcionando ahora!


No veo ningún problema obvio en el código.

"SELECT .. INTO" es un kung-fu débil. Intente crear explícitamente la definición de la tabla temporal:

CREATE TABLE #newMatches ( CompanyID int PRIMARY KEY, DunsID int )

Cuando hayas terminado con #newMatches, deberías deshacerte de él para que puedas volver a crearlo más tarde (¡las tablas temporales tienen acceso de conexión!)

DROP TABLE #newMatches


El código de activación (porque debe ejecutarse cada vez que se actualizan los datos) debe ser eficiente y debe tener en cuenta varias inserciones de registros. Has tenido éxito en el segundo pero no el primero. Ha hecho que esto sea demasiado complicado y ha utilizado elementos como No en las declaraciones que, por lo general, son menos efficeint que el uso de una combinación de la izquierda. Las tablas de temperatura son innecesarias aquí (nunca consideraría usar una en un desencadenante) ya que se suman a la ineficacia del desencadenante. No hay razón para no escribir desde insertado i en lugar de FROM (seleccione dunsId, nombre de #magic) i

El primero es probable que sea más rápido y más fácil de leer y mantener.

Aquí: JOIN (seleccione el caso cuando charindex (''/'', url) <> 0 luego a la izquierda (url, charindex (''/'', url) -1) else url end urlMatch, * de las empresas) c ON dandb.url = c .urlMatch

Está seleccionando todos los campos de la tabla, aunque parece que solo está utilizando uno. ¿Por qué? También está ejecutando esa versión de caso en todos los registros de la compañía, aunque después de unirse puede que no los necesite a todos.

También, en general, evitaría usar select * pero especialmente en un disparador. Supongamos que está insertando en otra tabla y utilizó select * de alguna tabla unida a insertada o eliminada. Agregar una columna a esa tabla haría que el desencadenador fallara y detuviera todos los cambios de datos hasta que se solucionara.

También usó una función en el disparador. Esto podría ser muy lento si tiene una inserción grande. Le sugiero que pruebe esto actualizando un gran grupo de registros y vea qué sucede. Todos los cambios de datos no ocurren solo desde la interfaz del usuario, un registro a la vez. Habrá momentos en que un campo se actualiza desde una consulta ad-hoc en el estudio de administración (cuando todos los precios deben ajustarse en un 10% como el ejemplo más simple que se le viene a la mente). Su desencadenante debe ser capaz de manejar esos tipos si actualizaciones, así como las que está esperando. Me gustaría ejecutar un caso de prueba actualizando 100000 filas y ver cuánto este disparador ralentiza las cosas.

Quizás esto realmente no está respondiendo a tu problema, pero el disparador está lejos de ser óptimo, tuve que decirlo.