Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
T-SQL触发器触发“列名称或提供的值数量与表定义不匹配”错误_Sql_Tsql_Triggers - Fatal编程技术网

T-SQL触发器触发“列名称或提供的值数量与表定义不匹配”错误

T-SQL触发器触发“列名称或提供的值数量与表定义不匹配”错误,sql,tsql,triggers,Sql,Tsql,Triggers,有件事我没能解决,我到处找了。也许这里会有人知道 我有一个名为dandb_raw的表,其中有三列:dunsId PK、name和searchName。我还有一个作用于此表的触发器: 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 sel

有件事我没能解决,我到处找了。也许这里会有人知道

我有一个名为dandb_raw的表,其中有三列:dunsId PK、name和searchName。我还有一个作用于此表的触发器:

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
出现此错误时:

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.
关于这一点,最奇怪的是触发器中的每个语句都独立工作。这几乎就好像inserted是一个一次性的表,如果您试图将inserted移动到临时表中,它会感染临时表


那么是什么导致触发器失败呢?如何停止它?

什么是公司\u联系人信息\u更新工具?实际参考中提到了程序公司_contactInfo _updateterries,但我在给出的代码中没有看到它。我也不知道它在哪里被称为。除非是您的应用程序在调用SQL,因此不相关


如果你测试了所有的东西,结果都成功了,但是现在它不起作用了,那么一定有什么不同。要考虑的一件事是安全。我注意到你只是称这个表为[dandbu_raw],而不是[dbo].[dandbu raw]。因此,如果用户有一个名为[user].[dandbu_raw]的表,那么该表将用于检查定义,而不是您的表。此外,触发器还创建临时表。但是,如果某些temp表由于任何原因已经存在,但定义不同,这也可能是一个问题。

我在代码中没有看到任何明显的问题

选择。。这是一门很弱的功夫。尝试显式创建临时表定义:

CREATE TABLE #newMatches
(
  CompanyID int PRIMARY KEY,
  DunsID int
)
当您使用完newMatches后,应该将其删除,以便以后可以再次创建它。临时表是连接作用域

DROP TABLE #newMatches

我认为大卫和塞尔沃在这一点上合二为一

我很确定我们在多个触发器中使用了newMatches。当一个触发器更改某些行时,它将触发另一个触发器,该触发器将尝试使用连接范围的newMatches

因此,它将尝试查找已经存在的具有不同模式的表,然后死亡,并生成上面的消息。有一条证据是有利的:inserted是否使用堆栈样式的作用域嵌套触发器有自己的inserted


但仍在猜测——至少现在一切似乎都在运转

触发器代码,因为它必须在每次更新数据时运行,因此必须高效,并且必须考虑多个记录插入。你第二次成功了,但第一次没有成功。您已经使这个问题变得过于复杂,并且在语句中使用了Not之类的语句,这些语句通常比使用左连接效率低。这里不需要临时表,我不会考虑在触发器中使用一个,因为它们增加了触发器的无效性。没有理由不写 从插入i 而不是 从select dunsId中,从magic i中选择名称

第一种可能更快,更易于阅读和维护

在这里: 当charindex'/',url 0,然后是lefturl,charindex'/',url-1 else url end urlMatch,*来自dandb.url=c.urlMatch上的公司c

您正在选择表中的所有字段,即使您似乎只使用了一个字段。为什么?您还将在公司的所有记录上运行case stament,即使您加入后可能不需要所有记录

一般来说,我会避免使用select*,尤其是在触发器中。假设您正在插入到另一个表中,并使用select*从某个已加入或已删除的表中选择。向该表中添加一列将导致触发器失败并停止所有数据更改,直到修复为止

您还在触发器中使用了一个函数。如果你有一个大的插入,这可能是痛苦的缓慢。我建议您通过更新大量记录来测试这一点,看看会发生什么。并非所有数据更改都是通过用户界面一次一条记录进行的。有时,当所有价格都需要调整10%时,ManagementStudio中的一个临时查询会更新一个字段,这是我想到的最简单的例子。您的触发器需要能够处理这些类型的更新以及您期望的更新。我会运行一个更新100000行的测试用例,看看这个触发器会降低多少速度


也许这并不能真正解决您的问题,但我不得不说,触发器远不是最佳的。

这非常有用……我错过了触发器公司\u contactInfo\u updateterrities。我将深入研究这个问题,看看是否能解决这个问题。也可以考虑使用变量表,因为它们的作用域是变量。
. 声明@newMatches TABLECompanyId int主键,DunsId实际上临时表已经不存在了。我不知道这些额外的栏目是干什么的,所以它们也不见了。我们最终必须在每一行上运行该函数。实际上,我们有一个很好的性能指标,因为我们进行批量加载。我可以禁用触发器,如果对批量使用过程更快…在批量加载后执行更新会比等效触发器更快吗?
DROP TABLE #newMatches