T-SQL, trigger di cottura una “Colonna nome o il numero di valori forniti non corrispondono definizione di tabella” errore
Domanda
Ecco qualcosa di cui non sono stato in grado di risolvere, e ho guardato ovunque.Forse qualcuno qui saprà!
Ho una tabella chiamata dandb_raw, con tre colonne in particolare:dunsId (PK), il nome e searchName.Ho anche un trigger che agisce in questa tabella:
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
Grilletto causa inserti a fallire:
insert into [dandb_raw](dunsId, name)
select 3442355, 'harper'
union all
select 34425355, 'har 466per'
update [dandb_raw] set name ='grap6767e'
Con questo errore:
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.
La cosa più curiosa è che ciascuna delle singole istruzioni del trigger lavora sul proprio.E ' quasi come se inserito una tabella che infetta le tabelle temporanee se si tenta di spostare inserito in uno di loro.
Così che cosa provoca il trigger a fallire?Come può essere fermato?
Soluzione
Penso che David e Cervo, hanno colpito il problema qui.
Sono abbastanza sicuro che una parte di ciò che stava accadendo era che stavamo usando #newMatches in più trigger.Quando un trigger cambiato alcune righe, sarebbe il fuoco di un altro trigger, che avrebbero tentato di utilizzare la connessione a livello di ambito di #newMatches.
Come risultato, si potrebbe provare a trovare la tabella già esistente con uno schema diverso, morire, e produrre il messaggio di cui sopra.Un pezzo di prova che sarebbe a favore:Non inserito utilizzare una pila di stile di ambito (nested trigger hanno la loro inserteds?)
Ancora speculando anche se - almeno le cose sembrano funzionare ora!
Altri suggerimenti
Che cosa è companies_contactInfo_updateTerritories?Il riferimento effettivo menziona la "procedura di companies_contactInfo_updateTerritories" ma non la vedo nel codice.Inoltre non vedo dove è in corso la chiamata.A meno che non sia dall'applicazione che si chiama SQL e quindi irrilevante....
Se hai provato tutto e tutto ha funzionato, ma adesso non funziona più, quindi qualcosa deve essere diverso.Una cosa da considerare è la sicurezza.Ho notato che ti basta chiamare il tavolo [dandb_raw] e non [dbo].[dandb_raw].Quindi, se l'utente ha una tabella con lo stesso nome [utente].[dandb_raw], la tabella dovrebbe essere utilizzato per controllare le definizioni invece della tabella.Inoltre, il trigger crea tabelle temporanee.Ma se alcuni di tabelle temporanee già esistente, per qualunque ragione, ma con definizioni diverse, questo può anche essere un problema.
Io non vedo alcun problema evidente nel codice.
"SELEZIONARE ..IN" è debole di kung-fu.Provare a creare esplicitamente la temp definizione di tabella:
CREATE TABLE #newMatches
(
CompanyID int PRIMARY KEY,
DunsID int
)
Quando hai finito con #newMatches, si dovrebbe sbarazzarsi di esso in modo da poter creare un secondo momento (temp sono le tabelle di collegamento con scope!!)
DROP TABLE #newMatches
Codice del Trigger (perché è necessario eseguire ogni volta che i dati sono aggiornati) deve essere efficace e deve tenere conto di più record inserti.Hai preso il secondo ma non il primo.Fatta questa troppo complicato e non hanno usato le cose come Non nelle dichiarazioni che sono di solito meno efficeint rispetto all'utilizzo di un left join.Temp tabelle sono inutili qui (non avrei mai considerare l'utilizzo di uno in un trigger) che aggiunge l'inefficienza del trigger.Non c'è motivo per non scrivere Inserite i invece di FROM (select dunsId, nome #magic) ho
Il primo è più veloce ed è più semplice da leggere e conservare.
Qui:JOIN ( select case quando charindex('/',url) <> 0, allora a sinistra(url, charindex ('/', ' url)-1) altro url fine urlMatch, * da parte di aziende ) c ON dandb.url = c.urlMatch
La selezione di tutti i campi della tabella, anche se è solo sembra essere uno.Perché?Si eseguono anche questo caso stament su tutti i record nella società, anche se dopo si entra non si può bisogno di tutti loro.
Anche in generale vorrei evitare di usare select*, ma soprattutto in un trigger.Supponiamo che si sta inserendo in un altro tavolo e si utilizza select * from qualche tabella unita alla inseriti o eliminati.Aggiungere una colonna alla tabella potrebbe causare l'innesco di fallire e di interrompere tutte le modifiche di dati fino a quando è stato risolto.
Se hai usato anche una funzione di trigger.Questo coudl essere dolorosamente lento, se si havea inserimento di grandi dimensioni.Ti suggerisco di verificare l'aggiornamento di un grande gruppo di record e vedere cosa succede.Tutti i dati modifiche non accadere solo dall'interfaccia utente, un record alla volta.Ci saranno momenti quando un campo viene aggiornato da una query ad hoc in management studio (quando tutti i prezzi devono essere regolati 10% come l'esempio più semplice che mi viene in mente.) Il trigger deve essere in grado di gestire questi tipi di aggiornamenti così come quelli che si aspettano.Vorrei eseguire un caso di test di aggiornamento 100000 righe e vedere quanto questo trigger rallenta cose.
Forse questa non è la risposta per il tuo problema, ma il grilletto appena è così lontano dall'essere ottimale, ho dovuto dire di si.