使用外键约束INSERT INTO表

时间:2015-07-23 20:47:22

标签: c# database ms-access foreign-key-relationship sql-insert

我已经阅读了一些内容,并提出了以下代码。我正在使用Access数据库,并通过Visual Studio在C#中编码。

我在这里遇到语法错误。我试图在Access中创建一个查询来测试它,但很难在其中创建它。

任何人都可以帮我弄清楚为什么这不起作用吗?

using(OleDbConnection conn1 = new OleDbConnection(global::InsulationProjectTracker.Properties.Settings.Default.InsulationDB))
{
    using(OleDbCommand command1 = conn1.CreateCommand())
    {
        conn.Open();

        command.CommandText = "INSERT INTO Jobsites (CustomerID, JobsiteName) VALUES ((SELECT Customers.CustomerID FROM Customers WHERE Customers.CustomerName = @cname1 AND Customers.BranchNumber = @bNumber1), @jName1)";
        command.Parameters.Add(new OleDbParameter("@cName1", cboCustomerName.Text));
        command.Parameters.Add(new OleDbParameter("@bNumber1", cboBranch.Text));
        command.Parameters.Add(new OleDbParameter("@jName1", txtJobsiteName.Text));

        command.ExecuteNonQuery();

        conn.Close();
        command.Parameters.Clear();

    }
}

表格设置

分行

PK BranchNumber
BranchName

客户

PK CustomerID
客户名称
FK BranchNumber

工地

PK JobsiteID
JobsiteName
FK CustomerID

EDIT ***

以下命令不会产生错误,但也不会将数据插入数据库

command.CommandText = "INSERT INTO Jobsites (CustomerID, JobsiteName) SELECT @jName1, c.CustomerID FROM Customers c WHERE c.CustomerName = @cname1 AND c.BranchNumber = @bNumber1";

5 个答案:

答案 0 :(得分:3)

Access SQL不接受目标表的别名。

例如,这些语句中的任何一个都会在INSERT INTO语句中触发"语法错误。" ...

INSERT INTO Jobsites j (j.CustomerID, j.JobsiteName) VALUES (1, 'foo');
INSERT INTO Jobsites AS j (j.CustomerID, j.JobsiteName) VALUES (1, 'foo');

没有别名,这个没有错误执行...

INSERT INTO Jobsites (CustomerID, JobsiteName) VALUES (1, 'foo');

为了获得查询,Access会接受,我认为您可能需要切换到INSERT ... SELECT而不是INSERT ... VALUES ...

command.CommandText = "INSERT INTO Jobsites (CustomerID, JobsiteName) SELECT c.CustomerID, @jName1 FROM Customers AS C WHERE c.CustomerName = @cname1 AND c.BranchNumber = @bNumber1";

基本上是@ConradFrix之前建议但没有 Jobsites 表的别名。

答案 1 :(得分:2)

KM在评论中提出的答案是正确的。不可能(并且没有理由)为command.CommandText = "INSERT INTO Jobsites (CustomerID, JobsiteName) VALUES ((SELECT c.CustomerID FROM Customers c WHERE c.CustomerName = @cname1 AND c.BranchNumber = @bNumber1), @jName1)"; 查询的目标设置别名。相反,它应该是

*

答案 2 :(得分:2)

嗯,参数名称需要@字符,就像你的查询一样

"INSERT INTO Jobsites j (j.CustomerID, j.JobsiteName) VALUES ((SELECT c.CustomerID FROM Customers c WHERE c.CustomerName = @cname1 AND c.BranchNumber = @bNumber1), @jName1)"

所以你需要改变

command.Parameters.Add(new OleDbParameter("cName1", cboCustomerName.Text));
                                    command.Parameters.Add(new OleDbParameter("bNumber1", cboBranch.Text));
                                    command.Parameters.Add(new OleDbParameter("jName1", txtJobsiteName.Text));

command.Parameters.Add(new OleDbParameter("@cName1", cboCustomerName.Text));
                                    command.Parameters.Add(new OleDbParameter("@bNumber1", cboBranch.Text));
                                    command.Parameters.Add(new OleDbParameter("@jName1", txtJobsiteName.Text));

答案 3 :(得分:2)

此部分VALUES ((SELECT c.CustomerID FROM Customers c WHERE c.Customer..是可疑的,因为使用SELECT获取单个值来获取customerID可能会非常棘手,因为多个CustomerID可能符合您的条件。

解决此问题的一种方法是将查询重写为

command.CommandText =@"
    INSERT INTO Jobsites j 
      (j.CustomerID, j.JobsiteName) 
    SELECT c.CustomerID ,  @jName1 as Jobsitename 
    FROM Customers c 
    WHERE c.CustomerName = @cname1 AND c.BranchNumber = @bNumber1";

这使用参数作为Jobsitename的常量,但它确实意味着如果返回多个记录,则会插入多行。

您可以通过添加TOP 1

来阻止返回多条记录的可能性

您还可以在数据库中查询客户ID,并在更新前检查行计数,如果您获得了多条记录,则抛出异常。这需要两次访问数据库,但可能更正确(除非您有一个关于客户名称的唯一索引)

答案 4 :(得分:2)

感谢大家帮忙解决这个问题。我根据您提供的输入更正了几项内容。

工作代码如下:

using(OleDbCommand command1 = conn1.CreateCommand())
{
    conn.Open();

    command.CommandText = "INSERT INTO Jobsites (JobsiteName, CustomerID) SELECT @jName1, c.CustomerID FROM Customers c WHERE c.CustomerName = @cname1 AND c.BranchNumber = @bNumber1";
    command.Parameters.Add(new OleDbParameter("@jName1", txtJobsiteName.Text));
    command.Parameters.Add(new OleDbParameter("@cName1", cboCustomerName.Text));
    command.Parameters.Add(new OleDbParameter("@bNumber1", cboBranch.Text));

    command.ExecuteNonQuery();

    conn.Close();
    command.Parameters.Clear();


}

主要问题是我需要使用INSERT SELECT和INSERT VALUES。一旦我改变了这一点,我所要做的就是重新定位参数并确保它们按顺序完成并且代码运行完美。

我还删除了INSERT INTO表中的别名,如此处所述。

非常感谢你们的帮助!

-Joseph