也许还没有开始喝咖啡,但是我很难解决如何完成SQL更新的问题。本质上,我有3个表,并且尝试根据表3中的条件使用表2中的数据更新表1中的字段。
我的3个带有示例数据的表:
tblInvoiceDetail
keyID InvoiceNumber ItemID Qty Price
--------------------------------------------------------
1 200123 100001 4 400
2 200123 100002 1 10
3 200321 100001 1 100
4 200555 100002 2 20
5 200444 100003 4 20
tbl发票
keyID InvoiceNumber InvoiceDate CustomerID InvoiceTotal
--------------------------------------------------------------------------
1 200123 3/15/19 456123 410
2 200321 5/31/19 123456 100
3 200555 6/30/19 111222 120
4 200444 6/31/19 111222 20
tblItemUpdate
keyID OldItem NewItem
----------------------------------
1 100001 999001
2 100002 999002
3 100003 999003
这是我尝试过的UPDATE
语句,但不会更新我期望的所有记录。
UPDATE
tblInvoiceDetail
SET
tblInvoiceDetail.ItemID = tblItemUpdate.NewItem
FROM
tblInvoiceDetail
INNER JOIN
tblItemUpdate ON tblInvoiceDetail.ItemID = tblItemUpdate.OldItem
INNER JOIN
tblInvoices ON tblInvoiceDetail.InvoiceNumber = tblInvoices.InvoiceNumber
WHERE
tblInvoices.InvoiceDate < '2019-06-25'
我怀疑问题出在我的JOIN中,所以它与我想要的所有记录都不匹配。
我想在tblInvoiceDetail中更改 ItemID ,并且希望它在 tblItemUpdate.OldItem 中找到匹配项,并将其更改为 tblItemUpdate.NewItem中的值。但是,我只想在 tblInvoices.InvoiceDate 在19/25/19之前更新ItemID。
因此,使用我的示例数据在tblInvoiceDetail中,只需更新keyID 1、2和3。
我的实时数据库中有很多记录,因此我可以指出1项无效的特定内容。我刚刚发现了一些我认为应该更改但没有更改的发票。
答案 0 :(得分:1)
编写此代码的标准方法是使用子查询:
UPDATE tblInvoiceDetail
SET ItemID = (SELECT NewItem FROM tblItemUpdate WHERE OldItem = tblInvoiceDetail.ItemID)
WHERE InvoiceNumber IN (
SELECT id.InvoiceNumber
FROM tblInvoiceDetail AS id INNER JOIN tblItemUpdate AS iu ON id.ItemID = iu.OldItem
WHERE id.InvoiceDate < CAST('2019-06-25' AS DATE)
);
Ezlo已经指出了在连接到已更新的表中创建多行时的问题。
编辑:
仔细查看您的数据,我还发现您在将ItemID
与正确的发票匹配时遇到了更大的问题。 tblInvoiceDetail
中的主键是InvoiceNumber
和ItemID
的组合,但您似乎没有从tblItemUpdate
的列表中找到该信息。
由于示例数据包含6月31日的无效日期,因此很自然地想知道是否存在字符串比较问题。主键问题可能会索要比预期更多的发票,因此不会解释您的问题,因为行更新少于预期。
答案 1 :(得分:0)
我想更改tblInvoiceDetail中的ItemID,并希望它找到 tblItemUpdate.OldItem中的匹配项并将其更改为 tblItemUpdate.NewItem
到目前为止:
UPDATE D SET
ItemID = U.NewItem
FROM
tblInvoiceDetail AS D
INNER JOIN tblItemUpdate AS U ON D.ItemID = U.OldItem
但是,我只想在tblInvoices.InvoiceDate时更新ItemID 是19年6月25日之前。
您可以使用EXISTS
检查是否存在:
UPDATE D SET
ItemID = U.NewItem
FROM
tblInvoiceDetail AS D
INNER JOIN tblItemUpdate AS U ON D.ItemID = U.OldItem
WHERE
EXISTS (SELECT NULL FROM tblInvoices AS I WHERE
I.InvoiceNumber = D.InvoiceNumber AND -- Link the invoice to update (D) to the invoice table (I)
I.InvoiceDate < '2019-06-25')
请注意您的InvoiceDate
数据类型。它应该是DATE
(或DATETIME
)而不是VARCHAR
,因为每当您将它与其他值('6/25/19'
和'2019-06-25'
进行比较时,都会带来麻烦。都是日期,但是它们是 完全不同的字符串 )。
还要当心OldItem
上存在多个具有相同tblItemUpdate
值的行,因为您可能正在将tblInvoiceDetail
中的特定行与tblItemUpdate
中的N连接起来在这种情况下,将要更新的最终NewItem
值为 indetermined 。