简体   繁体   中英

INSERT INTO table with foreign key contraints

I have read a couple things on this and came up with the following code. I am using an Access database and am coding in C# through Visual Studio.

I am getting a syntax error in this. I have tried to create a query in Access to test this but its difficult to create this in that.

Can anyone help me figure out why this isnt working?

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();

    }
}

Tables setup

Branches

PK BranchNumber
BranchName

Customers

PK CustomerID
CustomerName
FK BranchNumber

Jobsites

PK JobsiteID
JobsiteName
FK CustomerID

EDIT***

the below commmand produces no error, but also doesnt insert data into database

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

Access SQL does not accept an alias for the destination table.

For example, either of these statements trigger "Syntax error in INSERT INTO statement." ...

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

Without the alias, this one executes without error ...

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

In order to get a query Access will accept, I think you may need to switch to an INSERT ... SELECT instead of 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";

So basically what @ConradFrix suggested earlier but without the alias for the Jobsites table.

The answer suggested by KM in a comment is correct. It is not possible (and there is no reason) to alias the target of an INSERT INTO query. Instead, it should be

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

Well, Parameters name need the @ character, like in your query

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

so you need to change

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

to

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

This part VALUES ((SELECT c.CustomerID FROM Customers c WHERE c.Customer.. is suspicious because using a SELECT for a single value to get the customerID might be tricky becuase of the potential of more than one CustomerID that meets your criteria.

One way to solve this is to rewrite the query to

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";

This uses a parameter as a constant for Jobsitename but it does mean that if more than one record was returned you'd get mulitple rows inserted.

You could prevent the possiblity of more than one record being returned by adding TOP 1

You could also query the database for the customer ID and check the row count before updating and throwing an exception if you did get more than one record. This would require two trips to the db but is possibly more correct (unless of course you have a unique index on customer name)

Thank you all for your help in solving this. I corrected several things based on the input that you provided.

The working code is as follow:

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();


}

The main issue was i needed to use INSERT SELECT vs INSERT VALUES. Once i changed this, all i had to do was reposition the parameters and make sure they were in order and the code ran perfectly.

I also removed the alias designation on the INSERT INTO table as noted on here.

Thank you guys very much for your help!

-Joseph

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM