Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/84.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
Sql 如何解决;自引用表与外键约束“冲突”;_Sql_Sql Server_Sql Server 2008 - Fatal编程技术网

Sql 如何解决;自引用表与外键约束“冲突”;

Sql 如何解决;自引用表与外键约束“冲突”;,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我正在创建一个简单的表,其中包含自动生成的员工id,前缀如下 sale_900000,sale_900001,sale_900002,sale_900003 它是一个自引用表 在表中插入数据时,会出现如下错误: *Msg 547,16级,状态0,程序tr_生成emp_id,第42行 INSERT语句与外键相同表约束“Registration\u Registration”冲突。冲突发生在数据库“test”、表“dbo.Registration”、列“empid”中* 对于自动员工id,我在表

我正在创建一个简单的表,其中包含自动生成的
员工id
,前缀如下

sale_900000,sale_900001,sale_900002,sale_900003 
它是一个自引用表

在表中插入数据时,会出现如下错误:

*Msg 547,16级,状态0,程序tr_生成emp_id,第42行
INSERT语句与外键相同表约束“Registration\u Registration”冲突。冲突发生在数据库“test”、表“dbo.Registration”、列“empid”中*

对于自动员工id,我在表上使用
而不是insert
触发器

这是我的桌子

CREATE TABLE [dbo].[Registration](
    [empid] [varchar](40) NOT NULL,
    [id] [int] IDENTITY(900000,1) NOT NULL,
    [First_Name] [varchar](40) NULL,
    [Last_Name] [varchar](40) NULL,
    [Address] [varchar](40) NULL,
    [E_Mail] [varchar](40) NULL,
    [Country] [varchar](40) NULL,
    [Mobile_No] [varchar](40) NULL,
    [Designation] [varchar](40) NULL,
    [managerID] [varchar](40) NULL,
 CONSTRAINT [PK_Registration] PRIMARY KEY CLUSTERED 
(
    [empid] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[Registration]  WITH CHECK ADD  CONSTRAINT [Registration_Registration] FOREIGN KEY([managerID])
REFERENCES [dbo].[Registration] ([empid])
这是我的扳机

ALTER TRIGGER [dbo].[tr_generate_emp_id] ON [dbo].[Registration]
    INSTEAD OF INSERT
AS
    BEGIN
        DECLARE @id INT
        DECLARE @id1 INT
        DECLARE @id_s VARCHAR(50)

        DECLARE @empid VARCHAR(50)
        DECLARE @First_Name VARCHAR(50)
        DECLARE @Last_Name VARCHAR(50)
        DECLARE @Address VARCHAR(50)
        DECLARE @E_Mail VARCHAR(50)
        DECLARE @Country VARCHAR(50)
        DECLARE @Mobile_No VARCHAR(50)
        DECLARE @Designation VARCHAR(50)
        DECLARE @managerID VARCHAR(50)

            SELECT  @id = Id
            FROM   dbo.Registration
             IF @id IS NULL
             SET @id = 899999

              SET @id1 = @id + 1
           SELECt  @First_Name = First_Name ,
                    @Last_Name = Last_Name ,
                    @Address = Address ,
                    @E_Mail = E_Mail ,
                    @Country = Country ,
                    @Mobile_No = Mobile_No ,
                    @Designation = Designation ,
                    @managerID = managerID 

            FROM    INSERTED

              SET @id_s = CONVERT(VARCHAR(50), @id1)
              SET @empid = 'Sale_' + @id_s

             INSERT INTO dbo.Registration
                      ( empid ,
                        First_Name ,
                        Last_Name ,
                        Address ,
                        E_Mail ,
                        Country ,
                        Mobile_No ,
                        Designation ,
                        managerID 

                      )
              VALUES  ( @empid , -- empid - varchar(40)
                        @First_Name , -- First_Name - varchar(40)
                        @Last_Name  , -- Last_Name - varchar(40)
                        @Address , -- Address - varchar(40)
                        @E_Mail , -- E_Mail - varchar(40)
                        @Country, -- Country - varchar(40)
                        @Mobile_No , -- Mobile_No - varchar(40)
                        @Designation  , -- Designation - varchar(40)
                        @managerID -- managerID - varchar(40)
                      )
    END
我正在插入

INSERT INTO dbo.Registration
        ( empid ,
          First_Name ,
          Last_Name ,
          Address ,
          E_Mail ,
          Country ,
          Mobile_No ,
          Designation ,
          managerID
        )
VALUES  ( '' , -- empid - varchar(40)
          'admin' , -- First_Name - varchar(40)
          'jon' , -- Last_Name - varchar(40)
          's-24' , -- Address - varchar(40)
          'abc@gmail.com' , -- E_Mail - varchar(40)
          'india' , -- Country - varchar(40)
          '098735322211' , -- Mobile_No - varchar(40)
          'manager' , -- Designation - varchar(40)
          ''  -- managerID - varchar(40)
        )
和错误

Msg 547, Level 16, State 0, Procedure tr_generate_emp_id, Line 42
The INSERT statement conflicted with the FOREIGN KEY SAME TABLE constraint "Registration_Registration". The conflict occurred in database "test", table "dbo.Registration", column 'empid'.
The statement has been terminated.

主要的问题是你首先要做的就是这样。我刚看完你的扳机。刚刚将empid更改为计算字段

CREATE TABLE [dbo].[Registration](
    [empid] AS ('Sale_' + Convert(Varchar(50),id)) PERSISTED,
    [id] [int] IDENTITY(900000,1) NOT NULL,
    [First_Name] [varchar](40) NULL,
    [Last_Name] [varchar](40) NULL,
    [Address] [varchar](40) NULL,
    [E_Mail] [varchar](40) NULL,
    [Country] [varchar](40) NULL,
    [Mobile_No] [varchar](40) NULL,
    [Designation] [varchar](40) NULL,
    [managerID] [varchar](40) NULL,
 CONSTRAINT [PK_Registration] PRIMARY KEY CLUSTERED 
(
    [empid] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

在你的扳机里我想这条线

SELECT  @id = Id
是用来阅读的

SELECT  @id = MAX(Id)
我很惊讶你没有因此收到PK违规错误。FK冲突错误只能是由于尝试插入与empid值不匹配的MangerId值(从代码中我可以看到)。因此,请检查您提供的managerId值

  • 检查你的巢位
  • 我将把这个值放在(dbo.)AuditTable中,它与主表无关。 触发器_nestlevel()

  • 从基于行的逻辑更改为基于集的逻辑

  • 我重新设置了触发器,但我认为@Love2Learn可能有更好的解决方案

    ALTER TRIGGER [dbo].[tr_generate_emp_id] ON [dbo].[Registration]
        INSTEAD OF INSERT
    AS
        BEGIN
        DECLARE @id INT
    
            -- Get the last id used.
            SELECT  @id = MAX(Id)
            FROM   dbo.Registration
    
            IF @id IS NULL
                SET @id = 899999
    
             WITH MyInserted AS (SELECT
                            ROW_NUMBER() OVER(ORDER BY E_Mail) AS rownum-- Email is just a random order by here.  Could be anything you want.
                            ,*  
                            FROM inserted)
             INSERT INTO dbo.Registration
                      ( empid ,
                        First_Name ,
                        Last_Name ,
                        Address ,
                        E_Mail ,
                        Country ,
                        Mobile_No ,
                        Designation ,
                        managerID 
    
                      )
             SELECT -- add the last id used with the rownum (ranges from 1 to num of rows)
                    'Sale_'+CONVERT(VARCHAR(50), @id+rownum) -- empid - varchar(40)
                    First_Name, -- First_Name - varchar(40)
                    Last_Name, -- Last_Name - varchar(40)
                    Address,  -- Address - varchar(40)
                    E_Mail, -- E_Mail - varchar(40)
                    Country, -- Country - varchar(40)
                    Mobile_No, -- Mobile_No - varchar(40)
                    Designation, -- Designation - varchar(40)
                    ManagerID  -- managerID - varchar(40)
            FROM MyInserted
    END
    

    您的第一个问题是…触发器是基于集合的,而不是基于行的。我相信问题在于你创造了一个永无止境的触发器。您尝试插入到触发触发器的表中,该触发器表示,而不是插入到表中做一些工作,然后插入到表中,但我相信插入将再次触发触发器,从而重新启动流程,并导致无休止的循环。在插入记录后,我会根据一些逻辑对插入的记录进行更新。第二个问题是。。。您
    在触发器中选择@id
    ,可能会返回任何现有行。无法保证此逻辑将为您提供一个未使用的@id值。改为使用
    MAX()
    ,或者更好地使用after触发器中现有的
    IDENTITY
    列。这样可以查看整个问题@Love2Learn的答案要好得多,anway触发器通常是要避免的,如下所述: