【问题标题】:Foreign Key conflict on INSERT statementINSERT 语句上的外键冲突
【发布时间】:2018-03-16 13:30:34
【问题描述】:

我正在开发一个 WinForm 桌面应用程序供用户输入员工退休数据,使用 SQL Server 2008 作为数据库。

其中一个获取部分用户数据的表引用了另一个表,该表的记录是在设计时定义的,添加了外键约束以保持一致性。

CREATE TABLE tbCongedo (
    ID int IDENTITY(0,1) PRIMARY KEY,
    ID_ANAGRAFICA int NOT NULL,
    ID_TIPOLOGIA int NOT NULL,
    DECORRENZA datetime NOT NULL,
    PROT_NUM nvarchar(7) NOT NULL,
    PROT_DATA datetime NOT NULL
    );

CREATE TABLE tbTipologia (
    ID int IDENTITY(0,1) PRIMARY KEY,
    TIPOLOGIA nvarchar(20)
    );

INSERT INTO tbTipologia VALUES ('CONGEDO'), ('POSTICIPO'), ('ANTICIPO'), ('REVOCA'), ('DECESSO')

ALTER TABLE tbCongedo
ADD CONSTRAINT FK_tbCongedo_tbTipologia
FOREIGN KEY (ID_TIPOLOGIA) REFERENCES tbTipologia(ID)

然后,我有这段代码应该执行INSERT 语句

public int Insert(SqlConnection Connessione)
{
    using (SqlCommand Comando = new SqlCommand("INSERT INTO tbCongedo VALUES (@ID_ANAGRAFICA, @PROT_NUM, @PROT_DATA, @DECORRENZA, @ID_TIPOLOGIA); SELECT SCOPE_IDENTITY()", Connessione))
    {
        Comando.Parameters.AddWithValue("@ID_ANAGRAFICA", ID_ANAGRAFICA);
        Comando.Parameters.AddWithValue("@PROT_NUM", PROT_NUM);
        Comando.Parameters.AddWithValue("@PROT_DATA", PROT_DATA);
        Comando.Parameters.AddWithValue("@DECORRENZA", DECORRENZA);
        Comando.Parameters.AddWithValue("@ID_TIPOLOGIA", ID_TIPOLOGIA);

        ID = Int32.Parse(Comando.ExecuteScalar().ToString());
    }
    return ID;
}

但我得到了这个 SqlException:

INSERT 语句与 FOREIGN KEY 约束“FK_tbCongedo_tbTipologia”冲突。冲突发生在数据库“Scadenziario_ver4_TEST”、表“dbo.tbTipologia”、列“ID”中

这些是我试图插入表中的数据:

ID_ANAGRAFICA = 2
ID_TIPOLOGIA = 0
PROT_DATA = {16/03/2018 00:00:00}
DECORRENZA = {16/03/2018 00:00:00}
PROT_NUM = 123456

有趣的是,当我尝试通过 SQL Server Management Studio 手动插入这些相同的数据时,我根本没有收到任何错误。

谢谢。-

【问题讨论】:

  • FK表中是否有“0”的记录?
  • @Patrick 是的,这些是在设计时添加的。 0:Congedo,1:Posticipo 2...等等。
  • 暂停Execute 行的代码,并查看您将要尝试插入的值。然后查询 FK 表并确保那里已经有匹配的值。您的数据中的某些内容并非您认为的那样,而且您尚未对其进行调查。
  • 我还要仔细检查您是否已连接到您认为已连接到的数据库。
  • 鉴于您可以在 SSMS 中插入它,很明显您的应用程序中存在问题。你传递了一些你认为自己没有传递的价值。这里稍微偏离主题,但您应该避免使用 AddWithValue,因为您使用的是临时查询。它并不总是正确解释数据类型。 blogs.msmvps.com/jcoehoorn/blog/2014/05/12/…

标签: c# sql-server winforms desktop-application


【解决方案1】:

尝试指定字段:(col_name1, col_name2, ...)

否则,VALUES 可能不会像您希望的那样应用。变量名称不会自动与名称相似的列匹配。

像这样:

... new SqlCommand
(
    "INSERT INTO tbCongedo " +
    "       (ID_ANAGRAFICA, PROT_NUM, PROT_DATA, DECORRENZA, ID_TIPOLOGIA) "
    "VALUES (@ID_ANAGRAFICA, @PROT_NUM, @PROT_DATA, @DECORRENZA, @ID_TIPOLOGIA); " + 
    "SELECT SCOPE_IDENTITY()", Connessione
)
...

【讨论】:

  • 好收获。我没有注意到列顺序到处都是。
  • 在 INSERT 语句中不包含列列表是一个非常糟糕的习惯。我希望 OP 已经吸取了他的教训。
【解决方案2】:

我认为问题不在于数据,而在于INSERT 语句本身。您正在尝试使用错误的顺序将值插入错误的列。要解决此问题,您应该指定 INSERT 语句中的列或更正值的顺序。在您的情况下,查询将尝试在 ID_TIPOLOGIA 中插入 @PROT_NUM 的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多