T-SQL, trigger di cottura una “Colonna nome o il numero di valori forniti non corrispondono definizione di tabella” errore

StackOverflow https://stackoverflow.com/questions/95218

  •  01-07-2019
  •  | 
  •  

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?

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top