【发布时间】:2023-03-16 06:06:01
【问题描述】:
编辑:
为了稍微清理一下 SQL,我按照 PeterHE 的建议编写了代码,并硬编码(仅用于测试)测试值。现在我收到一条新的错误消息:“in_eq_Equipment.in_eq_CategoryID_fk”无法绑定。”
这是修改后的测试代码:
select in_eq_ID, in_eq_TagNumber as TagNumber, Title1Item, in_eq_AssetDescription as Description, in_eq_ExtendedDescription as ExtendedDescription, in_eq_SerialNumber as SerialNumber, in_eq_ValuationAmount as TotalValue, in_eq_CustodianName as Name, in_eq_ComplexBuilding as ShortLocation, in_eq_SubLocationCode as ShortRoomNumber, in_ca_Categories.in_ca_CategoryName as CategoryName, in_eq_DispositionDate as DispositionDate, Departments.DepartmentCode, DATEADD (dd, 0, DATEDIFF (dd, 0, in_eq_Equipment.in_eq_AcquisitionDate)) as AcquisitionDate
from in_eq_Equipment, Departments
LEFT JOIN in_ca_Categories ON in_eq_Equipment.in_eq_CategoryID_fk = in_ca_Categories.in_ca_CategoryID
where in_eq_Equipment.DepartmentID = CAST ('00000000-0000-0000-0000-000000000000' AS nvarchar(36)) and upper (in_eq_AssetDescription) LIKE upper ('%T$')
生锈的老程序员回来了...尝试测试存储过程并遇到此错误消息。错误:
消息 137,级别 15,状态 2,第 18 行 必须声明标量变量“@DepartmentID”。
// 测试调用代码:
DECLARE @SearchString varchar(30), @DispositionText varchar(200)
declare @DepartmentID uniqueidentifier;
SET @SearchString = 'T'
SET @DispositionText = '';
SET @DepartmentID = '00000000-0000-0000-0000-000000000000';
EXEC GetInventoryByAssetDescription @SearchString, @DispositionText, @DepartmentID
实际的存储过程代码(是的,我知道这是不好的代码——我最初没有编写它,但必须在短时间内修改它):
USE [Inventory]
GO
/****** Object: StoredProcedure [dbo].[GetInventoryByAssetDescription] Script Date: 12/23/2019 9:09:51 AM ******/
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
ALTER PROCEDURE [dbo].[GetInventoryByAssetDescription]
(
@SearchString varchar(30),
@DispositionText varchar(200) = null,
@DepartmentID uniqueidentifier
)
AS
begin
SET NOCOUNT ON
declare @sql nvarchar (2000)
select @SearchString=UPPER(@SearchString)
set @sql = ' select in_eq_ID,
in_eq_TagNumber as TagNumber,
Title1Item,
in_eq_AssetDescription as Description,
in_eq_ExtendedDescription as ExtendedDescription,
in_eq_SerialNumber as SerialNumber,
in_eq_ValuationAmount as TotalValue,
in_eq_CustodianName as Name,
in_eq_ComplexBuilding as ShortLocation,
in_eq_SubLocationCode as ShortRoomNumber,
in_ca_Categories.in_ca_CategoryName as CategoryName,
in_eq_DispositionDate as DispositionDate,
Departments.DepartmentCode,
DATEADD (dd, 0, DATEDIFF (dd, 0, in_eq_Equipment.in_eq_AcquisitionDate)) as AcquisitionDate
from in_eq_Equipment, Departments
where in_eq_Equipment.DepartmentID = @DepartmentID
LEFT JOIN in_ca_Categories ON in_eq_Equipment.in_eq_CategoryID_fk = in_ca_Categories.in_ca_CategoryID
WHERE upper (in_eq_AssetDescription) LIKE upper ('''+ @SearchString + ''')
'
set @sql=@sql+' ' + ISNULL(@DispositionText,' ') + ' order by in_eq_AssetDescription'
execute (@sql)
return
end
【问题讨论】:
-
是的,这很糟糕。不仅糟糕 - 可怕。它有很多问题。重复的上层逻辑,老风格的join,设备和部门之间看似错误的join,dispositiontext很容易出错。最重要的是 - 容易受到 SQL INJECTION 的影响。
-
如果允许修改存储过程,为什么要使用动态SQL,因为它性能很差。您的 SQL SELECT 中没有任何内容需要动态参数。一切都是直截了当的,仅从输入中获取。我想说,只需删除该动态 sql 逻辑,有一个普通的 SQL SELECT 语句,它只根据输入参数查询您各自的表。
-
这个原始的 SQL 显然是在 2005 年创建的。我太生疏了,在时间线下,怀疑我有时间彻底清理它。只是试图在这一点上做一个小的修改。感谢您的意见。
-
你所拥有的没有意义。
@DispositionText是什么?你只是将它注入到你的语句中,这是没有意义的。你为什么交叉加入departments?不应该是INNER JOIN,然后将@DepartmentID与departments表中的列进行比较吗?为什么你也有 2 个WHERE子句? -
“这个原始 SQL 显然是在 2005 年创建的”,并且在 2005 年永远不会工作。
FROM TAble1, Table2 WHERE Table1.Col = 1 LEFT JOIN Table3 ON...的语法完全错误。
标签: sql-server scalar