T-SQL löst einen „Spaltennamen oder Anzahl der übergebenen Werte nicht Tabellendefinition“ Brennen Fehler

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

  •  01-07-2019
  •  | 
  •  

Frage

Hier ist etwas, das ich zu reparieren nicht in der Lage gewesen zu sein, und ich habe sah überall . Vielleicht hat jemand hier wissen!

Ich habe eine Tabelle dandb_raw, mit drei Spalten insbesondere genannt: dunsId (PK), Namen und search. Ich habe auch einen Auslöser, der auf dieser Tabelle handelt:

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

Der Auslöser bewirkt, dass Einsätze zum Scheitern verurteilt:

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

Mit diesem Fehler:

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.

Das Merkwürdigste daran ist, dass jeder der einzelnen Aussagen im Trigger auf seinem eigenen Werke. Es ist fast, als ob eingefügt ist eine einmalige Tabelle, die temporären Tabellen infiziert, wenn Sie versuchen, in einem von ihnen eingefügt zu bewegen.

Also, was bewirkt, dass der Auslöser zum Scheitern verurteilt? Wie kann es gestoppt werden?

War es hilfreich?

Lösung

Ich denke, David und Cervo haben hier das Problem betroffen kombiniert.

Ich bin mir ziemlich sicher, dass ein Teil von dem, was geschieht, dass wir #newMatches in mehr Trigger verwendet hat. Wenn ein Trigger einige Zeilen geändert, würde es einen weiteren Trigger ausgelöst, die die Verbindung #newMatches scoped zu verwenden versuchen würde.

Als Ergebnis würde es versuchen, finden die Tabelle bereits mit einem anderen Schema existiert, sterben, und produzieren die obige Meldung. Ein Beweis, dass zugunsten wäre: eingefügt Nutzt einen Stapel Stil Rahmen (geschachtelte Trigger haben ihre eigenen inserteds?)

spekulieren Noch aber - zumindest die Dinge scheinen zu funktionieren jetzt

!

Andere Tipps

Was ist companies_contactInfo_updateTerritories? Die eigentliche Referenz erwähnt Prozedur „companies_contactInfo_updateTerritories“ aber ich sehe es nicht in dem Code angegeben. Auch sehe ich nicht, wo es genannt wird. Es sei denn, es ist aus Ihrer Anwendung, die die SQL ruft und daher irrelevant ....

Wenn Sie alles getestet und es funktioniert, aber jetzt funktioniert es nicht, dann muss etwas anderes sein. Eine Sache zu prüfen ist die Sicherheit. Ich habe bemerkt, dass Sie nur die Tabelle rufen [dandb_raw] und nicht [dbo]. [Dandb_raw]. Also, wenn der Benutzer eine Tabelle mit dem gleichen Namen [user] hatte. [Dandb_raw], würde die Tabelle verwendet, um die Definitionen anstelle der Tabelle zu überprüfen. Außerdem erzeugt der Trigger temporäre Tabellen. Aber wenn einige der temporären Tabellen bereits bestanden aus irgendeinem Grunde aber mit unterschiedlichen Definitionen, dies kann auch ein Problem sein.

Ich habe kein offensichtliches Problem in dem Code sehen.

"SELECT .. INTO" ist schwach Kung-Fu. Versuchen Sie explizit die temporäre Tabellendefinition zu erstellen:

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

Wenn Sie mit #newMatches fertig sind, sollten Sie es loswerden, so dass Sie es später erneut erstellen können (temporäre Tabellen sind Verbindung scoped !!)

DROP TABLE #newMatches

Trigger-Code (weil es laufen muss jedes Mal die Daten aktualisiert werden) müssen effizient sein und für mehrere Rekordeinsätze entfallen müssen. Sie haben in der zweiten gelang es aber nicht die erste. Sie haben diese zu kompliziert gemacht und Dinge wie nicht in Anweisungen verwendet, die in der Regel weniger efficeint sind sich ein linke als verwenden. Temp-Tabellen sind nicht notwendig hier (Ich würde nie in einem Trigger), wie sie auf die Ineffizienz des Abzugs hinzuzufügen. Es Grund ist nicht, nicht zu schreiben Von eingefügt i Anstatt von  FROM (wählen dunsId, Namen von #magic) i

Die erste ist wahrscheinlich schneller und einfacher zu lesen und zu erhalten.

Hier: JOIN (wählt Fall, wenn charindex ( '/', URL) <> 0, dann links (url, charindex ( '/', URL) -1) else url Ende urlMatch, * von Unternehmen) c ON dandb.url = c.urlMatch

Sie sind die Auswahl aller Felder in der Tabelle, auch wenn Sie nur eine zu sein scheinen verwenden. Warum? Sie sind auch diesen Fall abgetan auf alle Datensätze in Unternehmen laufen, obwohl, nachdem Sie kommen Sie nicht alle von ihnen benötigen.

Auch im Allgemeinen würde ich mit select * vermeiden, aber vor allem in einem Trigger. Angenommen, Sie in eine andere Tabelle einfügen, und Sie verwendet select * from einige Tabelle eingefügt oder gelöscht verbunden. Hinzufügen einer Spalte zu dieser Tabelle würde dazu führen, den Auslöser zum Scheitern verurteilt und alle Datenänderungen zu stoppen, bis es repariert wurde.

Sie habe auch eine Funktion in Abzug. Diese coudl quälend langsam sein, wenn Sie großen Einsatz havea. Ich schlage vor, Sie dies testen, indem eine große Gruppe von Datensätzen zu aktualisieren und sehen, was passiert. Alle Datenänderungen geschehen nicht nur von der Benutzeroberfläche, einen Datensatz zu einem Zeitpunkt. Es wird Zeiten geben, wenn ein Feld aus einer Ad-hoc-Abfragen in Management Studio aktualisiert wird (wenn alle Preise um 10% als einfachstes Beispiel angepasst werden müssen, die in dem Sinne kommt.) Ihre Auslöser brauchen diese Art zu handhaben zu können, wenn Updates sowie die, die Sie erwarten. Ich würde einen Testfall zu aktualisieren 100000 Reihen laufen und sehen, wie viel dieser Trigger Dinge verlangsamt.

Vielleicht ist das nicht wirklich das Problem zu beantworten, aber der Auslöser nur so bei weitem nicht optimal, ich hatte es zu sagen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top