今天在解决公司C#项目bug问题,顺便记录一下问题及解决方案。入库日报表和出库日报表执行查询失败: ‘DATE’ 不是可以识别的 内置函数名称。
问题截图如下:
这个错误信息看起来是由于在执行远程方法 SIE.WMS.Statistics.StatisticsController.GetDayOutStocks 时发生了异常。具体的错误信息是 “‘Date’ 不是可以识别的内置函数名称”,同时附近有语法错误,关键字 ‘AS’ 附近存在问题。
报错详细日志如下:
> Exception has been thrown by the target of an invocation.->远程方法
> SIE.WMS.Statistics.StatisticsController.GetDayOutStocks(DayOutStockViewModelCriteria)
> 执行失败:'Date' 不是可以识别的 内置函数名称。 关键字 'AS' 附近有语法错误。 SELECT [T1].[NAME] AS
> [Warehouse], DateName(year,dm.collect_date) YEAR,
> DateName(month,dm.collect_date) MONTH, [dm].[COLLECT_DATE] AS
> [OutStockDate], SUM([p].[SHIPPING_QTY]) AS [DeliverQty],
> MAX([dm].[ITEM_QTY]) AS [ItemQty], MAX([T2].[BILL_QTY]) AS [BillQty]
> FROM [SHIPPING_ORDER_DTL] AS [p] INNER JOIN [SHIPPING_ORDER] AS [T0]
> ON [p].[SHIPPING_ORDER_ID] = [T0].[ID] AND [T0].[INV_ORG_ID] = 1 AND
> [T0].[IS_PHANTOM] = False INNER JOIN [WH] AS [T1] ON
> [T0].[SHIPPING_WARE_HOUSE_ID] = [T1].[ID] AND [T1].[INV_ORG_ID] = 1
> AND [T1].[IS_PHANTOM] = False INNER JOIN (SELECT 0 id,
> [d1].[COLLECT_DATE] AS [Collect_Date], [d1].[WAREHOUSE_ID] AS
> [Warehouse_Id], COUNT([d1].[ITEM_ID]) AS [Item_Qty] FROM (SELECT
> DISTINCT d.shipping_date collect_date, [a].[SHIPPING_WARE_HOUSE_ID] AS
> [Warehouse_Id], [d].[ITEM_ID] AS [Item_Id] FROM [SHIPPING_ORDER_DTL]
> AS [d] INNER JOIN [SHIPPING_ORDER] AS [a] ON [d].[SHIPPING_ORDER_ID] =
> [a].[ID] AND [a].[INV_ORG_ID] = 1 AND [a].[IS_PHANTOM] = False WHERE
> [d].[ORDER_STATE] = 80 AND [d].[SHIPPING_QTY] > 0 AND [d].[INV_ORG_ID]
> = 1 AND [d].[IS_PHANTOM] = False) AS [d1] GROUP BY [d1].[COLLECT_DATE], [d1].[WAREHOUSE_ID]) AS [dm] ON
> [dm].[WAREHOUSE_ID] = [T0].[SHIPPING_WARE_HOUSE_ID] AND
> [dm].[COLLECT_DATE] = Date(p.shipping_date) INNER JOIN (SELECT 0 id,
> [d1].[COLLECT_DATE] AS [Collect_Date], [d1].[WAREHOUSE_ID] AS
> [Warehouse_Id], COUNT([d1].[SO_ID]) AS [Bill_Qty] FROM (SELECT
> DISTINCT d.shipping_date collect_date, [a].[SHIPPING_WARE_HOUSE_ID] AS
> [Warehouse_Id], [a].[ID] AS [So_Id] FROM [SHIPPING_ORDER_DTL] AS [d]
> INNER JOIN [SHIPPING_ORDER] AS [a] ON [d].[SHIPPING_ORDER_ID] =
> [a].[ID] AND [a].[INV_ORG_ID] = 1 AND [a].[IS_PHANTOM] = False WHERE
> [d].[ORDER_STATE] = 80 AND [d].[SHIPPING_QTY] > 0 AND [d].[INV_ORG_ID]
> = 1 AND [d].[IS_PHANTOM] = False) AS [d1] GROUP BY [d1].[COLLECT_DATE], [d1].[WAREHOUSE_ID]) AS [T2] ON
> [T2].[WAREHOUSE_ID] = [T0].[SHIPPING_WARE_HOUSE_ID] AND
> [T2].[COLLECT_DATE] = Date(p.shipping_date) WHERE [p].[ORDER_STATE] =
> 80 AND [p].[SHIPPING_QTY] > 0 AND [p].[SHIPPING_DATE] >=
> to_date('2023/12/10 0:00:00','yyyy-mm-dd hh24:mi:ss') AND
> [p].[SHIPPING_DATE] < to_date('2023/12/17 0:00:00','yyyy-mm-dd
> hh24:mi:ss') AND [p].[INV_ORG_ID] = 1 AND [p].[IS_PHANTOM] = False
> GROUP BY [T1].[NAME], [dm].[COLLECT_DATE];->'Date' 不是可以识别的 内置函数名称。 关键字
> 'AS' 附近有语法错误。 SELECT [T1].[NAME] AS [Warehouse],
> DateName(year,dm.collect_date) YEAR, DateName(month,dm.collect_date)
> MONTH, [dm].[COLLECT_DATE] AS [OutStockDate], SUM([p].[SHIPPING_QTY])
> AS [DeliverQty], MAX([dm].[ITEM_QTY]) AS [ItemQty],
> MAX([T2].[BILL_QTY]) AS [BillQty] FROM [SHIPPING_ORDER_DTL] AS [p]
> INNER JOIN [SHIPPING_ORDER] AS [T0] ON [p].[SHIPPING_ORDER_ID] =
> [T0].[ID] AND [T0].[INV_ORG_ID] = 1 AND [T0].[IS_PHANTOM] = False
> INNER JOIN [WH] AS [T1] ON [T0].[SHIPPING_WARE_HOUSE_ID] = [T1].[ID]
> AND [T1].[INV_ORG_ID] = 1 AND [T1].[IS_PHANTOM] = False INNER JOIN
> (SELECT 0 id, [d1].[COLLECT_DATE] AS [Collect_Date],
> [d1].[WAREHOUSE_ID] AS [Warehouse_Id], COUNT([d1].[ITEM_ID]) AS
> [Item_Qty] FROM (SELECT DISTINCT d.shipping_date collect_date,
> [a].[SHIPPING_WARE_HOUSE_ID] AS [Warehouse_Id], [d].[ITEM_ID] AS
> [Item_Id] FROM [SHIPPING_ORDER_DTL] AS [d] INNER JOIN [SHIPPING_ORDER]
> AS [a] ON [d].[SHIPPING_ORDER_ID] = [a].[ID] AND [a].[INV_ORG_ID] = 1
> AND [a].[IS_PHANTOM] = False WHERE [d].[ORDER_STATE] = 80 AND
> [d].[SHIPPING_QTY] > 0 AND [d].[INV_ORG_ID] = 1 AND [d].[IS_PHANTOM] =
> False) AS [d1] GROUP BY [d1].[COLLECT_DATE], [d1].[WAREHOUSE_ID]) AS
> [dm] ON [dm].[WAREHOUSE_ID] = [T0].[SHIPPING_WARE_HOUSE_ID] AND
> [dm].[COLLECT_DATE] = Date(p.shipping_date) INNER JOIN (SELECT 0 id,
> [d1].[COLLECT_DATE] AS [Collect_Date], [d1].[WAREHOUSE_ID] AS
> [Warehouse_Id], COUNT([d1].[SO_ID]) AS [Bill_Qty] FROM (SELECT
> DISTINCT d.shipping_date collect_date, [a].[SHIPPING_WARE_HOUSE_ID] AS
> [Warehouse_Id], [a].[ID] AS [So_Id] FROM [SHIPPING_ORDER_DTL] AS [d]
> INNER JOIN [SHIPPING_ORDER] AS [a] ON [d].[SHIPPING_ORDER_ID] =
> [a].[ID] AND [a].[INV_ORG_ID] = 1 AND [a].[IS_PHANTOM] = False WHERE
> [d].[ORDER_STATE] = 80 AND [d].[SHIPPING_QTY] > 0 AND [d].[INV_ORG_ID]
> = 1 AND [d].[IS_PHANTOM] = False) AS [d1] GROUP BY [d1].[COLLECT_DATE], [d1].[WAREHOUSE_ID]) AS [T2] ON
> [T2].[WAREHOUSE_ID] = [T0].[SHIPPING_WARE_HOUSE_ID] AND
> [T2].[COLLECT_DATE] = Date(p.shipping_date) WHERE [p].[ORDER_STATE] =
> 80 AND [p].[SHIPPING_QTY] > 0 AND [p].[SHIPPING_DATE] >=
> to_date('2023/12/10 0:00:00','yyyy-mm-dd hh24:mi:ss') AND
> [p].[SHIPPING_DATE] < to_date('2023/12/17 0:00:00','yyyy-mm-dd
> hh24:mi:ss') AND [p].[INV_ORG_ID] = 1 AND [p].[IS_PHANTOM] = False
> GROUP BY [T1].[NAME], [dm].[COLLECT_DATE];
后台debug调试直接抛异常
查看详细异常message
同时去sqlserver执行sql,同样也是报错!
判断可能是自定义函数拼接错误!
初步分析: 可能是由于拼写错误、未声明函数或者不正确的使用导致的。接下来我们需要去后台检查代码中与 ‘Date’ 相关的部分代码,确保其正确性。
定位排查问题
后台断点调试
定位应该是这两行代码 导致错误。
query.Join<Asn, DayInStockItemSum>("dm", (h, dm) => dm.WarehouseId == h.WarehouseId && dm.CollectDate == h.SQL<DateTime>("Date(p.collect_date)"));
query.Join<Asn, DayInStockBillSum>((h, db) => db.WarehouseId == h.WarehouseId && db.CollectDate == h.SQL<DateTime>("Date(p.collect_date)"));
这是代码段使用自定义函数将 p.shipping_date 转换为日期类型的 SQL 查询。在这里,使用了 SQL(“Date(p.shipping_date)”) 来执行这个转换。
然而,这样的写法可能导致 SQL 注入的风险。如果 p.shipping_date 是用户输入的值,直接将其嵌入 SQL 语句可能会导致安全问题。
解决方案: 最好的做法是使用参数化查询,以避免潜在的安全漏洞。
下面是修改后的代码,使用参数化查询:
query.Join<Asn, DayInStockItemSum>("dm", (h, dm) => dm.WarehouseId == h.WarehouseId && dm.CollectDate == h.SQL<DateTime>("collect_date)"));
query.Join<Asn, DayInStockBillSum>((h, db) => db.WarehouseId == h.WarehouseId && db.CollectDate == h.SQL<DateTime>("collect_date"));
优化一下代码逻辑,添加一个判断(判断是否是SqlServer数据库服务器,添加这两行语句)
这里,我使用了 h.Param(“shipping_date”) 来表示参数化的日期。
最后,前端页面执行查询,问题解决ok!