尝试执行时出错。我不是DBA,但是我需要根据传入的变量来过滤where子句。我使用IF语句的大量语句工作,但看起来非常糟糕,所以我想出了这个想法但是却出错了
查询:
DECLARE
@VariableName AS NVARCHAR(100),
@VariableValue AS NVARCHAR(MAX),
@PileFrom AS INT,
@PileTo AS INT,
@BeginDate AS DATETIME,
@EndDate AS DATETIME,
@Truck AS BIT,
@Train AS BIT
--AS
BEGIN
IF @BeginDate = '' BEGIN
SET @Begindate = '1/1/1900'
END
IF @EndDate = '' BEGIN
SET @EndDate = '1/1/9999'
END
IF @Truck = 1 BEGIN
SELECT
Car_ID,
PO_Number,
Vendor,
Shipper,
Commodity,
Date_Weighed_In,
Date_Weighed_Out,
Pile_No AS 'PILe From',
Pile_No1 AS 'Pile To',
Operator_In,
Operator_Out,
Comments_In,
Comments_Out,
Weight_In,
Weight_Out,
Transaction_Num,
Record_time_Stamp
FROM
dbo.Transactions_Truck
WHERE
(Date_Weighed_IN BETWEEN @BeginDate AND @EndDate) AND
CASE
WHEN @VariableName = 'rbCardID' THEN Car_ID = @VariableValue
WHEN @VariableName = 'rbPONumber' THEN PO_Number = @VariableValue
WHEN @VariableName = 'rbVendor' THEN Vendor = @VariableValue
WHEN @VariableName = 'rbCommodity' THEN Commodity = @VariableValue
WHEN @VariableName = 'rbPileNumber' THEN Pile_No = @PileFrom AND Pile_No1 = @PileTo
WHEN @VariableName = 'rbTransactionNum' THEN Transaction_Num = @VariableValue
WHEN @VariableName = 'rbOperator' THEN Operator_In = @VariableValue
WHEN @VariableName = 'rbComments' THEN Comments_In = @VariableValue
END ELSE IF @Train = 1 BEGIN
SELECT
Car_ID,
PO_Number,
Vendor,
Shipper,
Commodity,
Date_Weighed_In,
Date_Weighed_Out,
Pile_No AS 'PILe From',
Pile_No1 AS 'Pile To',
Operator_In,
Operator_Out,
Comments_In,
Comments_Out,
Weight_In,
Weight_Out,
Transaction_Num,
Record_time_Stamp
FROM
dbo.Transactions_train
WHERE
(Date_Weighed_IN BETWEEN @BeginDate AND @EndDate) AND
CASE
WHEN @VariableName = 'rbCardID' THEN Car_Id = @VariableValue
WHEN @VariableName = 'rbPONumber' THEN PO_Number = @VariableValue
WHEN @VariableName = 'rbVendor' THEN Vendor = @VariableValue
WHEN @VariableName = 'rbCommodity' THEN Commodity = @VariableValue
WHEN @VariableName = 'rbPileNumber' THEN Pile_No = @PileFrom AND Pile_No1 = @PileTo
WHEN @VariableName = 'rbTransactionNum' THEN Transaction_Num = @VariableValue
WHEN @VariableName = 'rbOperator' THEN Operator_In = @VariableValue
WHEN @VariableName = 'rbComments' THEN Comments_In = @VariableValue
WHEN @VariableName = 'rbRailRoad' THEN Rail_Road = @VariableValue
END
END
答案 0 :(得分:2)
你不能做那样的where语句..你应该只使用AND和OR
WHERE (Date_Weighed_IN BETWEEN @BeginDate AND @EndDate)
AND (
(@VariableName = 'rbCardID' AND Car_Id = @VariableValue)
OR (@VariableName = 'rbPONumber' AND PO_Number = @VariableValue)
OR (@VariableName = 'rbVendor' AND Vendor = @VariableValue)
OR (@VariableName = 'rbCommodity' AND Commodity = @VariableValue)
OR (@VariableName = 'rbPileNumber' AND Pile_No = @PileFrom
AND Pile_No1 = @PileTo )
OR (@VariableName = 'rbTransactionNum' AND Transaction_Num = @VariableValue)
OR (@VariableName = 'rbOperator' AND Operator_In = @VariableValue)
OR (@VariableName = 'rbComments' AND Comments_In = @VariableValue)
OR (@VariableName = 'rbRailRoad' AND Rail_Road = @VariableValue)
)
答案 1 :(得分:1)
JamieD77
的答案应该做的工作,但是很多OR可能会让你遇到性能问题,所以我也会考虑使用dynamic SQL
来尝试获得更小的SQL语句执行(这没有经过测试,我已经重新格式化以使其更具可读性):
DECLARE @SQL NVARCHAR(4000) = '
SELECT Car_ID, PO_Number, Vendor, Shipper, Commodity, Date_Weighed_In, Date_Weighed_Out, Pile_No AS [PILe From],
Pile_No1 AS [Pile To], Operator_In, Operator_Out, Comments_In, Comments_Out, Weight_In, Weight_Out,
Transaction_Num, Record_time_Stamp
FROM dbo.Transactions_Truck
WHERE (Date_Weighed_IN BETWEEN @BeginDate AND @EndDate)'
-- merge conditions that are common to @Train = 0 and @Train = 1
IF (@VariableName = 'rbCardID') @SQL = @SQL + CHAR(13) + CHAR(10) + N' AND Car_ID = @VariableValue'
IF (@VariableName = 'rbPONumber') @SQL = @SQL + CHAR(13) + CHAR(10) + N' AND PO_Number = @VariableValue'
-- other conditions come here
IF (@VariableName = 'rbComments') @SQL = @SQL + CHAR(13) + CHAR(10) + N' AND Comments_In = @VariableValue'
IF (@Train = 1 AND @VariableName = 'rbRailRoad') @SQL = @SQL + CHAR(13) + CHAR(10) + N' AND Rail_Road = @VariableValue'
-- for debugging purposes
PRINT @SQL
EXEC sp_executesql @SQL, N'@BeginDate DATETIME, @EndDate DATETIME, @VariableValue NVARCHAR(MAX)',
@BeginDate = @BeginDate, @EndDate = @EndDate, @VariableValue = @VariableValue
这样你的代码就更DRY了,我认为你应该更快(我不知道引擎是否知道优化所有这些OR,这可能比使用动态可能丢失的性能更糟糕查询)。
更好的方法是以打字的方式进行比较。与@VariableValue
相比,我看不到所有列的数据类型,但我认为Ids和日期不是字符串。如果类型与NVARCHAR
不同,则将为每种类型的不匹配生成隐式转换,性能将降低。
但是,这需要使用Entity Framework完全重写您的逻辑(如果这是您的程序正在进行的所有内容并且这是很好的练习,那么这应该不是很难)或类似的东西。