0

私はSQLが初めてです。データベースに 2 つの新しいテーブルを追加しました。first の主キーは、other の外部キーです。キーの型は整数です。ここで、テーブルの異なる行間の関連付けが正しくなるように、コードでキーを生成し、それを新しいデータに割り当てたいと考えています。キーの一意性を確保し、データベースから最新のキーを取得して、保存中にエラーが発生しないようにするにはどうすればよいですか。

GUID を使用していた場合は、新しい GUID を主キーに割り当て、それを別のテーブルの外部キーに割り当てます。また、複数のクライアントと、データを保存している 1 つのサーバーがあります。

両方のテーブルに挿入されるデータは、C# コードで決定され、プライマリ テーブルに挿入された行から派生したものではありません。db で id を取得したとしても、行間の関係もコードから何らかの形式で保存する必要があります。その後は失われるためです。

4

2 に答える 2

16

これを行う唯一の実行可能な方法INT IDENTITYは、SQL Server データベースが提供するものを使用することです。これを信じてください - あなたはこれを自分でやろうとはしません!

使うだけ

CREATE TABLE dbo.YourTableOne(ID INT IDENTITY(1,1),  ...other columns...)

そしてそれで終わります。

最初のテーブルに行を挿入すると、次のように ID 列の値を取得できます。

-- do the insert into the first table
INSERT INTO dbo.YourTableOne(Col1, Col2, ...., ColN)
VALUES (Val1, Val2, ...., ValN)

DECLARE @NewID INT

-- get the newly inserted ID for future use
SELECT @NewID = SCOPE_IDENTITY()

-- insert into the second table, use first table's new ID for your FK column
INSERT INTO dbo.YourTableTwo (FKColumn, ......) VALUES(@NewID, ......)

更新:複数の行を最初のテーブルに挿入し、生成された複数の値を取得する必要がある場合は、次の句IDを使用します。OUTPUT

-- declare a table variable to hold the data
DECLARE @InsertedData TABLE (NewID INT, ...some other columns as needed......)

-- do the insert into the first table
INSERT INTO dbo.YourTableOne(Col1, Col2, ...., ColN)
OUTPUT Inserted.ID, Inserted.Col1, ..., Inserted.ColN INTO @InsertedData(NewID, Col1, ..., ColN)
VALUES (Val1, Val2, ...., ValN)

そしてそこから行きます。新しく挿入された行から任意の値を一時テーブル変数に取得できます。これにより、2 番目のテーブルのどの行にどの新しい ID 値を使用するかを決定できます。

于 2013-07-30T16:11:13.727 に答える
2

@marc_s が言ったように、データベースで管理されたキーを使用する方が実行可能です。ただし、同時に作業するユーザーが少ない場合など、データベースに大きな負荷がかからない場合は、別のより簡単な方法を使用します。これで最後の ID を取得し、新しいレコードを追加しようとしました。重複のエラーが発生した場合は、もう一度試します。私のアプリケーションではこれを 3 回の試行に制限し、各試行の間に 300 ミリ秒のタイムアウトがあります。このアプローチには重大な制限があることを忘れないでください。私のアプリケーションでは、ユーザー数は非常に少なく、作業負荷は非常に低く、接続はローカル接続であるため、うまく機能します。おそらく他のアプリケーションでは、遅延を調整する必要があり、場合によっては、アプローチ完全に失敗する可能性があります。コードは次のとおりです。2 つのテーブルがInvoicesありInvoices_Items、それらを関連付ける列は次のinvoice_idとおりです。

        byte attempts = 0;

      tryagain:  //Find last invoice no

        OleDbCommand command = new OleDbCommand("SELECT MAX(invoice_id) FROM Invoices"
                 , myconnection);
            int last_invoice_id = 0;
            try
            {
                last_invoice_id = (int)command.ExecuteScalar();
            }
            catch (InvalidCastException) { };

           // text_invoice_number.Text = Convert.ToString(last_invoice_id + 1);

            try
            {
                command = new OleDbCommand(@"INSERT INTO Invoices
      (invoice_id,patient_id,visit_id,issue_date,invoice_to,doctor_id,assistant_id)
     VALUES(?,?,?,?,?,?,?)",myconnection);
   // We use last_invoice_id+1 as primary key
   command.Parameters.AddWithValue("@invoice_id",last_invoice_id+1);
            // I will add other parameters here (with the exact order in query)
                command.ExecuteNonQuery();
            }
            catch (Exception ex){
                attempts++;
                if (attempts <= 3)  // 3 attempts
                {
                    System.Threading.Thread.Sleep(300); // 300 ms second delay
                    goto tryagain;
                }
                else
                {
                    MessageBox.Show("Can not add invoice to database, " + ex.Message,   "Unexpected error!"
                        , MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

        for (int i = 0; i <= listInvoiceItems.Count-1; i++)
        {
               command = new OleDbCommand(@"INSERT INTO Invoices_Items
                                 (invoice_id,quantity,product,price,amount,item_type)
                                        VALUES(?,?,?,?,?,?)",myconnection);
       // Now we use our stored last_invoice_id+1 as foreign key
             command.Parameters.AddWithValue("@invoice_id",last_invoice_id+1); 
         // Add other Invoice Items parameters here (with the exact order in query)
        command.ExecuteNonQuery();
        }
于 2013-08-12T07:12:35.800 に答える