T-SQL löst einen „Spaltennamen oder Anzahl der übergebenen Werte nicht Tabellendefinition“ Brennen Fehler
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?
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.