在包含*** UNION、INTERSECT 或 EXCEPT 运算符的语句中不允许变量赋值
Posted
技术标签:
【中文标题】在包含*** UNION、INTERSECT 或 EXCEPT 运算符的语句中不允许变量赋值【英文标题】:Variable assignment is not allowed in a statement containing a top level UNION, INTERSECT or EXCEPT operator 【发布时间】:2010-11-09 21:45:57 【问题描述】:运行 SQL 2008 R2。这个过程在 VS 2008 DB 项目中通过了验证,但在管理工作室中失败了。有什么想法吗?
CREATE PROCEDURE [dbo].[WRHS_chkBinTransferItem]
(
@BinFromID int,
@BarCodeNumber varchar(50),
@Count int,
@Message varchar(500) OUTPUT
)
AS
DECLARE
@LotTrackIND int,
@ItemID int,
@QtyAvail int,
@LotNumber varchar(50)
SELECT @ItemID = i.ItemID, @LotTrackIND = i.LotTrackingInd, @LotNumber = ''
FROM WRHS_ItemUOM iu
INNER JOIN WRHS_Item i ON iu.ItemID = i.ItemID
WHERE iu.BarcodeNumber = @BarCodeNumber
UNION
SELECT @ItemID = i.ItemID, @LotTrackIND = i.LotTrackingInd, @LotNumber = wil.LotNumber
FROM WRHS_WarehouseItemLotIdentify wili
INNER JOIN WRHS_WarehouseItemLot wil ON wili.WarehouseItemLotID = wil.WarehouseItemLotID
INNER JOIN WRHS_WarehouseItem wi ON wil.WarehouseItemID = wi.WarehouseItemID
INNER JOIN WRHS_Item i ON wi.ItemID = i.ItemID
WHERE wili.ItemIdentification = @BarCodeNumber
IF @LotTrackIND = 1
BEGIN
IF @ItemID > 0
BEGIN
SELECT DISTINCT @QtyAvail = q.Qty
FROM WRHS_BinItem bi
INNER JOIN WRHS_BinItemQty q ON bi.BinItemID = q.BinItemID
WHERE bi.BinID = @BinFromID AND bi.ItemID = @ItemID AND q.LotNumber = @LotNumber
IF @Count <= @QtyAvail
BEGIN
SELECT DISTINCT q.BinItemQtyID, RTRIM(i.ItemNumber) as ItemNumber, i.LicensePlateInd, q.LotNumber, i.LotTrackingInd, i.ItemID, wi.ForcedPutAwayInd
FROM WRHS_Bin b
INNER JOIN WRHS_BinItem bi ON b.BinID = bi.BinID
INNER JOIN WRHS_BinItemQty q ON bi.BinItemID = q.BinItemID
INNER JOIN WRHS_Item i On bi.ItemID = i.ItemID
INNER JOIN WRHS_WarehouseItem wi ON b.WarehouseID = wi.WarehouseID AND i.ItemID = wi.ItemID
WHERE b.BinID = @BinFromID AND bi.ItemID = @ItemID AND q.LotNumber = @LotNumber
SET @Message = 'Success'
END
ELSE
BEGIN
SET @Message = 'Selected Quantity not Available'
END
END
ELSE
BEGIN
SET @Message = 'Invalid BarCode Scan, this Item is Lot Tracked and the proper BarCode must be scanned.'
END
END
ELSE
BEGIN
IF @ItemID > 0
BEGIN
SELECT DISTINCT @QtyAvail = q.Qty
FROM WRHS_BinItem bi
INNER JOIN WRHS_BinItemQty q ON bi.BinItemID = q.BinItemID
WHERE bi.BinID = @BinFromID AND bi.ItemID = @ItemID AND q.LotNumber = @LotNumber
IF @Count <= @QtyAvail
BEGIN
SELECT DISTINCT q.BinItemQtyID, RTRIM(i.ItemNumber) as ItemNumber, i.LicensePlateInd, q.LotNumber, i.LotTrackingInd, i.ItemID, wi.ForcedPutAwayInd
FROM WRHS_Bin b
INNER JOIN WRHS_BinItem bi ON b.BinID = bi.BinID
INNER JOIN WRHS_BinItemQty q ON bi.BinItemID = q.BinItemID
INNER JOIN WRHS_ItemUOM iu ON bi.ItemID = iu.ItemID
INNER JOIN WRHS_Item i On bi.ItemID = i.ItemID
INNER JOIN WRHS_WarehouseItem wi ON b.WarehouseID = wi.WarehouseID AND i.ItemID = wi.ItemID
WHERE b.BinID = @BinFromID AND bi.ItemID = @ItemID AND q.LotNumber = @LotNumber
SET @Message = 'Success'
END
ELSE
BEGIN
SET @Message = 'Selected Quantity not Available'
END
END
ELSE
BEGIN
SET @Message = 'Invalid BarCode Scan'
END
END
【问题讨论】:
在 UNION 中 - 它的两边是互斥的吗?意思是,是否有WRHS_ITEM
记录通过WRHS_ITEMUOM
具有条形码但没有WRHS_WarehouseItemLotIdentify
- 反之亦然?根据这一点,可以将查询重写为单个查询。
【参考方案1】:
对于作业,部分,你可以借助子查询来计算,例如:
Select @ItemID = ItemID, @LotTrackIND = LotTrackingInd, @LotNumber = LotNumber
from (
SELECT i.ItemID, i.LotTrackingInd, '' LotNumber
FROM WRHS_ItemUOM iu
INNER JOIN WRHS_Item i ON iu.ItemID = i.ItemID
WHERE iu.BarcodeNumber = @BarCodeNumber
UNION
SELECT i.ItemID, i.LotTrackingInd, wil.LotNumber
FROM WRHS_WarehouseItemLotIdentify wili
INNER JOIN WRHS_WarehouseItemLot wil ON wili.WarehouseItemLotID = wil.WarehouseItemLotID
INNER JOIN WRHS_WarehouseItem wi ON wil.WarehouseItemID = wi.WarehouseItemID
INNER JOIN WRHS_Item i ON wi.ItemID = i.ItemID
WHERE wili.ItemIdentification = @BarCodeNumber
) q1
我警告您没有迭代您的查询可能返回的(可能的)多条记录。
最好的问候。
【讨论】:
【参考方案2】:在你的工会中你不能做变量赋值
SELECT @ItemID = i.ItemID, @LotTrackIND = i.LotTrackingInd, @LotNumber = ''
...
UNION
SELECT @ItemID = i.ItemID, @LotTrackIND = i.LotTrackingInd, @LotNumber = wil.LotNumber
...
正如错误所说。
至于为什么会传入VS,是VS的bug。
【讨论】:
【参考方案3】:是的,错误就在这部分,
SELECT @ItemID = i.ItemID, @LotTrackIND = i.LotTrackingInd, @LotNumber = ''
FROM WRHS_ItemUOM iu
INNER JOIN WRHS_Item i ON iu.ItemID = i.ItemID
WHERE iu.BarcodeNumber = @BarCodeNumber
UNION
SELECT @ItemID = i.ItemID, @LotTrackIND = i.LotTrackingInd, @LotNumber = wil.LotNumber
FROM WRHS_WarehouseItemLotIdentify wili
INNER JOIN WRHS_WarehouseItemLot wil ON wili.WarehouseItemLotID = wil.WarehouseItemLotID
INNER JOIN WRHS_WarehouseItem wi ON wil.WarehouseItemID = wi.WarehouseItemID
INNER JOIN WRHS_Item i ON wi.ItemID = i.ItemID
WHERE wili.ItemIdentification = @BarCodeNumber
如果语句具有 UNION,则不能使用 select 语句为变量赋值。如果你仔细想想,这没有任何意义。变量只能保存一个值,但它应该选择哪一个呢?第一个 select 语句中的那个还是第二个?
您必须明确做出该选择。假设您希望第二个 select 语句优先(即从第二个 select 中获取值。如果第二个 select 语句没有返回值,则取第一个返回的值),您可以这样做
SELECT @ItemID = i.ItemID, @LotTrackIND = i.LotTrackingInd, @LotNumber = ''
FROM WRHS_ItemUOM iu
INNER JOIN WRHS_Item i ON iu.ItemID = i.ItemID
WHERE iu.BarcodeNumber = @BarCodeNumber
SELECT @ItemID = i.ItemID, @LotTrackIND = i.LotTrackingInd, @LotNumber = wil.LotNumber
FROM WRHS_WarehouseItemLotIdentify wili
INNER JOIN WRHS_WarehouseItemLot wil ON wili.WarehouseItemLotID = wil.WarehouseItemLotID
INNER JOIN WRHS_WarehouseItem wi ON wil.WarehouseItemID = wi.WarehouseItemID
INNER JOIN WRHS_Item i ON wi.ItemID = i.ItemID
WHERE wili.ItemIdentification = @BarCodeNumber
【讨论】:
以上是关于在包含*** UNION、INTERSECT 或 EXCEPT 运算符的语句中不允许变量赋值的主要内容,如果未能解决你的问题,请参考以下文章
union all这样写为啥提示“使用 UNION、INTERSECT 或 EXCEPT 运算符合并的所有查询必须在其目标列表中有
SQL SERVER: 合并相关操作(Union,Except,Intersect) - 转载
Intersect.Union,Union All,Intersect,Minus区别
[讲解]sql except和intersect运算符(比拟两个或多个select语句的结果并前去非重复值)