简体   繁体   English

通过一个查询插入两个表

[英]Inserting into two tables with one query

What's wrong with my code, i tried to combine two query into one. 我的代码有什么问题,我尝试将两个查询合并为一个。 But the second query is not working, i already follow the answer of this link INSERT INTO two tables at one query but i think mine doesn't work, am i missing something in my code? 但是第二个查询不起作用,我已经按照这个链接的答案在一个查询中插入了两个表,但是我认为我的方法不起作用,我的代码中缺少什么吗?

string sql = "INSERT INTO tbladdbook(fBookTitle,fAuthor,fBookYr,fEdition,fPublication,fAccNo,fCallNo,fCategory,fBarCodeNo,fCurrentCopies) VALUES('"
                                    + txtTITLE.Text + "','"
                                    + txTAUTHOR.Text + "','"
                                    + txtBOOKYR.Text + "','"
                                    + txtEDITION.Text + "','"
                                    + txtPUBLICATION.Text + "','"
                                    + txtACCESSNO.Text + "','"
                                    + txtCALLNO.Text + "','"
                                    + txtCATEGORY.SelectedItem + "','"
                                    + txtBARCODE.Text + "','"
                                    + txtCOPIES.Text + "'); INSERT INTO tbltruecopies(fBookTitle,fAuthor,fBarCodeNo,fTrueCopies) VALUES('"
                                    + txtTITLE.Text + "','"
                                    + txTAUTHOR.Text + "','"
                                    + txtBARCODE.Text + "','"
                                    + txtCOPIES.Text + "')";

                            cfgotcall.inputQ(sql);

Table definition: for tbladdbook 表定义:用于tbladdbook

fBookTitle   varchar
fAuthor      varchar
fEdition     varchar
fBookYr      varchar
fPublication varchar
fAccNo       varchar
fCallNo      varchar
fCategory    varchar
fBarCodeNo   varchar
fCurrentCopies  float

Table definition: for tbltrue 表定义:用于tbltrue

fBookTitle  varchar
fAuthor     varchar
fBarCodeNo  bigint
fTrueCopies bigint

Old and working code: 旧的工作代码:

string sql = "INSERT INTO tbladdbook(fBookTitle,fAuthor,fBookYr,fEdition,fPublication,fAccNo,fCallNo,fCategory,fBarCodeNo,fCurrentCopies) VALUES('"
                                        + txtTITLE.Text + "','"
                                        + txTAUTHOR.Text + "','"
                                        + txtBOOKYR.Text + "','"
                                        + txtEDITION.Text + "','"
                                        + txtPUBLICATION.Text + "','"
                                        + txtACCESSNO.Text + "','"
                                        + txtCALLNO.Text + "','"
                                        + txtCATEGORY.SelectedItem + "','"
                                        + txtBARCODE.Text + "','"
                                        + txtCOPIES.Text + "')";

                                cfgotcall.inputQ(sql);

                                sql = "INSERT INTO tbltruecopies(fBookTitle,fAuthor,fBarCodeNo,fTrueCopies) VALUES('"
                                        + txtTITLE.Text + "','"
                                        + txTAUTHOR.Text + "','"
                                        + txtBARCODE.Text + "','"
                                        + txtCOPIES.Text + "')";

                                cfgotcall.inputQ(sql);

Captain Teemo asked if I was able to rewrite using parameters. 蒂莫船长问我是否能够使用参数进行重写。

This is a relatively easy operation; 这是一个相对容易的操作; however, I write for SQL Server and there may be slight differences with the MySql commands and I do not the cfgotcall methods ( is this Cold Fusion? ) that are being used for the Data Layer, so I will just write this in ADO. 但是,我是为SQL Server写的,与MySql命令可能会有细微的差别,并且我没有用于数据层的cfgotcall方法( 这是Cold Fusion吗? ),所以我只会在ADO中编写它。

In this case I simply replaced all of the values in the VALUES clause with SQL Variables, and basically reused the column names with a preceding @, so the column fBookTitle is assigned the value @fBookTitle . 在这种情况下,我只是用SQL变量替换了VALUES子句中的所有值,并基本上在前面的@处重用了列名,因此为fBookTitle列分配了值@fBookTitle Then we can assign those parameters to the command object via the Parameters.AddWithValue() method. 然后,我们可以通过Parameters.AddWithValue()方法将这些参数分配给command对象。 For the above @fBookTitle value the call would be cmd.Parameters.AddWithValue("@Title", txtTITLE.Text); 对于上述@fBookTitle值,调用将为cmd.Parameters.AddWithValue("@Title", txtTITLE.Text); I noticed that the variables being used in the second query were all in the first query, but not vice versa; 我注意到第二个查询中使用的变量都在第一个查询中,但反之则不然。 so I am going to build up execute Qry2 first, then we can simply change the CommandText and add in the additional parameters. 因此,我将首先构建执行Qry2 ,然后我们只需更改CommandText并添加其他参数即可。 One of the things with using parameters is that you will need to add the values with the correct type, so adding in a value that is a BigInt in the database will need to be added in as the corresponding C# type of Int64. 使用参数的一件事是您将需要添加具有正确类型的值,因此需要在数据库中添加作为BigInt的值作为相应的Int64 C#类型。

What I can do is show how this would be done via ADO with SQL Server, and you can modify what needs to be done. 我能做的是显示如何通过ADO与SQL Server来完成此操作,并且您可以修改需要完成的操作。 If you can't find a cfgotcall that works with parameters then you could just change this for use with MySql which has nearly identical syntax to the SQL Server syntax. 如果找不到适用于参数的cfgotcall ,则可以将其更改为与SQL语法几乎相同的MySql一起使用。

string Qry1 = "INSERT INTO tbladdbook(fBookTitle,fAuthor,fBookYr,fEdition,fPublication,fAccNo,fCallNo,fCategory,fBarCodeNo,fCurrentCopies) VALUES (@Title, @Author, @BookYr, @Edition, @Publication, @AccNo, @CallNo, @Category, @BarCode, @Copies)";
string Qry2 = "INSERT INTO tbltruecopies(fBookTitle, fAuthor, fBarCodeNo, fTrueCopies) VALUES (@Title, @Author, @Barcode, @Copies)";

using (SqlConnection conn = new SqlConnection(connectionstring)) {
    conn.Open();
    using (SqlCommand cmd = new SqlCommand()) {
        cmd.Connection = conn;
        cmd.CommandType = CommandType.Text;

        cmd.CommandText = Qry2;
        cmd.Parameters.AddWithValue("@Title", txtTITLE.Text);
        cmd.Parameters.AddWithValue("@Author", txTAUTHOR.Text);
        cmd.Parameters.AddWithValue("@Barcode", Int64.parse(txtBARCODE.Text));
        cmd.Parameters.AddWithValue("@Copies", Int64.parse(txtCOPIES.Text));
        try { cmd.ExecuteNonQuery(); }
        catch (Exception) { /* your error handling */ }

        cmd.CommandText = Qry1;
        cmd.Parameters.AddWithValue("@BookYr", txtBOOKYR.Text);
        cmd.Parameters.AddWithValue("@Edition", txtEDITION.Text);
        cmd.Parameters.AddWithValue("@Publication", txtPUBLICATION.Text);
        cmd.Parameters.AddWithValue("@AccNo", txtACCESSNO.Text);
        cmd.Parameters.AddWithValue("@CallNo", txtCALLNO.Text);
        cmd.Parameters.AddWithValue("@Category", txtCATEGORY.SelectedItem);
        try { cmd.ExecuteNonQuery(); }
        catch (Exception) { /* your error handling */ }

    }
    conn.Close();
}

Tetsuya Yamamoto suggests that this be converted over to a Stored Procedure 山本哲也建议将其转换为Stored Procedure

This is an easy enough task on SQL Server, but I do not know the MySql implementation; 在SQL Server上,这很容易完成,但是我不知道MySql的实现。 sorry you are going to get what I would be typing in Query Analyzer or SSMS, and this would most likely to be translated for MySql as well. 抱歉,您将得到我将在查询分析器或SSMS中键入的内容,并且很可能还会将其翻译成MySql。

The syntax for this procedure is going to be rather simple, as all we are going to do is wrap the 2 queries within it. 该过程的语法将非常简单,因为我们要做的就是将其中的两个查询包装在其中。

CREATE PROCEDURE usp_addBookAndCopies (
    @Title       VARCHAR(100),
    @Author      VARCHAR(100),
    @BookYr      VARCHAR(100),
    @Edition     VARCHAR(100),
    @Publication VARCHAR(100),
    @AccNo       VARCHAR(100),
    @CallNo      VARCHAR(100),
    @Category    VARCHAR(100),
    @BarCode     BIGINT,
    @Copies      BIGINT
) AS
BEGIN

    INSERT tbladdbook ( fBookTitle,  fAuthor,  fBookYr,  fEdition,  fPublication, 
                       fAccNo,  fCallNo,  fCategory,  fBarCodeNo,  fCurrentCopies  )
    VALUES            (@Title, @Author, @BookYr, @Edition, @Publication,
                      @AccNo, @CallNo, @Category, @BarCode, @Copies  )

    INSERT tbltruecopies ( fBookTitle, fAuthor, fBarCodeNo, fTrueCopies)
    VALUES               (@Title, @Author, @Barcode, @Copies)

END
GO

Once we have the Stored Procedure created, we would need to modify the original code, removing the 2 INSERT queries and replace them with the one command calling the procedure. 一旦创建了存储过程 ,我们将需要修改原始代码,删除2个INSERT查询,并将其替换为一个调用该过程的命令。 We would also change the command type to reflect that we are running a procedure instead of a text command. 我们还将更改命令类型以反映我们正在运行过程而不是文本命令。

// Not Needed: string Qry1 = "INSERT INTO tbladdbook..." 
// Not Needed: string Qry2 = "INSERT INTO tbltruecopies..." 
using (SqlConnection conn = new SqlConnection(connectionstring)) {
    conn.Open();
    using (SqlCommand cmd = new SqlCommand()) {
        cmd.Connection = conn;
        cmd.CommandType = CommandType.StoredProcedure; //  Changed
        cmd.CommandText = "usp_addBookAndCopies";      //  Changed

        cmd.Parameters.AddWithValue("@Title", txtTITLE.Text);
        cmd.Parameters.AddWithValue("@Author", txTAUTHOR.Text);
        cmd.Parameters.AddWithValue("@Barcode", Int64.parse(txtBARCODE.Text));
        cmd.Parameters.AddWithValue("@Copies", Int64.parse(txtCOPIES.Text));
        cmd.Parameters.AddWithValue("@BookYr", txtBOOKYR.Text);
        cmd.Parameters.AddWithValue("@Edition", txtEDITION.Text);
        cmd.Parameters.AddWithValue("@Publication", txtPUBLICATION.Text);
        cmd.Parameters.AddWithValue("@AccNo", txtACCESSNO.Text);
        cmd.Parameters.AddWithValue("@CallNo", txtCALLNO.Text);
        cmd.Parameters.AddWithValue("@Category", txtCATEGORY.SelectedItem);

        try { cmd.ExecuteNonQuery(); }
        catch (Exception) { /* your error handling */ }
    }
    conn.Close();
}

My Comments 我的评论

Looking at the actual statements and the code this appears to be adding books to a library of sorts. 查看实际的语句和代码,这似乎是将书籍添加到各种库中。 There is a table of Books ( tbladdbook ) and another for Book Copies ( tbltruecopies ), and the only thing different between the two tables is that Copies would reflect how many copies are currently on hand, but the Count is of dissimilar types; 有一个Books表( tbladdbook )和另一个Book Book副本( tbltruecopies ),这两个表之间唯一的不同是Copies将反映当前有多少副本,但是Count是不同的类型。 one being Float and the other as BigInt . 一个是Float ,另一个是BigInt My opinion would be that these two should be of the same type, and I really don't think it is realistic that these values would ever exceed the capacity of a 32 bit integer, if not 16 bit. 我的意见是这两个应该属于同一类型,而且我真的认为这些值超过16位的32位整数的容量是不现实的。 Not too mention that Float and Double are only approximations. 不太提及Float和Double仅是近似值。

This a rather long answer, and my aging eyes may have a syntax error or two. 这是一个相当长的答案,而且我的眼睛老化可能有一两个语法错误。 Please forgive me and let me know of any errors or suggestions, I will be happy to update this for you. 请原谅我,让我知道任何错误或建议,我们很乐意为您更新。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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