组, 我正在尝试使用一个变量@Customer创建一个存储过程。我想要做的是在WHERE子句中添加一些内容,说明它是否为数字搜索CustomerID字段,其中输入的数字为LIKE CustomerID ...如果输入了char,则搜索CustomerName字段,其中输入的文本为LIKE CustomerName。以下是我想要做的一个例子:
CREATE PROCEDURE [dbo].[uspGetCustomer] (@Customer VARCHAR(100))
AS
SET NOCOUNT ON
SELECT *
FROM dbo.Customers
WHERE CASE WHEN ISNUMERIC(@Customer) THEN CustomerID LIKE @Customer + '%'
ELSE CustomerName LIKE @Customer + '%' END
有什么建议吗?
答案 0 :(得分:4)
我会使用IF语句来实现,因为将该逻辑放在WHERE中会使以后难以阅读:
DECLARE @match = @CustomerID + '%'
IF ISNUMERIC(@CustomerID) = 1
BEGIN
SELECT * FROM CUSTOMERS WHERE CustomerID LIKE @match
END ELSE BEGIN
SELECT * FROM CUSTOMERS WHERE CustomerNAME LIKE @match
END
更新: 我想知道CustomerID字段是否是INT。如果是这样,那么我会像这样更改查询(并删除@match变量):
... WHERE CustomerID = Cast(@CustomerID as INT) --if numeric
... WHERE CustomerNAME = @CustomerID + '%' --if not numeric
但是,如果它是一个奇怪的VARCHAR字段以数字开头并以其他数据结尾,如'11_blah',则LIKE加通配符正常工作
答案 1 :(得分:3)
尝试解决这两个条件的单个SQL语句将导致最差的执行计划。记住SQL必须生成一个单独的计划来满足@variable的任何值。在你的情况下@customerID是数字时,正确的计划是使用CustomerID上的索引。但是当@customerID是一个名称时,正确的访问权限将是CustomerName的索引。鉴于这种困境,优化器可能会选择执行全扫描的计划,即。两种情况都没有优化。
正确的做法是确定应用中的 ,如果是ID或名称,并调用两个单独的存储过程,uspGetCustomerByID
和uspGetCustomerByName
,根据输入的值。如果你必须通过一个'魔术'API入口点(全能的uspGetCustomer
)来做到这一点,那么你已经得到了很好的答案。
答案 2 :(得分:3)
它可能只是我,但使用单个变量来表示两个不同的字段给了我糟糕的练习意志。我会重写这个存储过程以接受两个不同的可空变量(一个int,CustomerID和一个varchar,CustomerName)。它看起来像这样:
CREATE PROCEDURE [dbo].[uspGetCustomer] (
@CustomerID int = null,
@CustomerName VARCHAR(100) = null)
AS
IF @CustomerID IS NOT NULL BEGIN
SELECT * FROM Customers WHERE CustomerID = @CustomerID
END ELSE IF @CustomerName IS NOT NULL BEGIN
SELECT * FROM Customers WHERE CustomerName LIKE @CustomerName
END ELSE
--error handling, return empty set maybe?
END
如果这不是一个选项,那么你仍然可以使用:
CREATE PROCEDURE [dbo].[uspGetCustomer] (@Customer VARCHAR(100))
AS
DECLARE @NameMatch;
IF ISNUMERIC(@Customer) = 1 BEGIN
SELECT * FROM Customers WHERE CustomerID = CAST (@Customer AS int)
END ELSE BEGIN
SET @NameMatch = '%' + @Customer + '%'
SELECT * FROM Customers WHERE CustomerName LIKE @NameMatch
END
答案 3 :(得分:2)
使用:
CREATE PROCEDURE [dbo].[uspGetCustomer] (@Customer VARCHAR(100))
AS
BEGIN
IF ISNUMERIC(@Customer) = 1
BEGIN
SELECT *
FROM dbo.CUSTOMERS
WHERE customerid LIKE @Customer + '%'
END
ELSE
BEGIN
SELECT *
FROM dbo.CUSTOMERS
WHERE customername LIKE @Customer + '%'
END
END
答案 4 :(得分:2)
做这样的事情:
CREATE PROCEDURE [dbo].[uspGetCustomer] (
@CustomerID INT = NULL
@Customer VARCHAR(100) = NULL
)
AS
SET NOCOUNT ON
IF @CustomerID is not null
BEGIN
SELECT * FROM dbo.Customers
WHERE CustomerID = @CustomerID
END
ELSE
BEGIN
SELECT * FROM dbo.Customers
WHERE CustomerName LIKE @CustomerID + '%'
END
SET NOCOUNT OFF
答案 5 :(得分:1)
我会保持简单,并假设客户名称永远不会是数字:
SELECT *
FROM dbo.Customers
WHERE CustomerID LIKE @Customer + '%'
OR CustomerName LIKE @Customer + '%'
或者,如果您确实不希望将数字客户与其名称匹配,则可以检查如下:
WHERE (IsNumeric(@Customer) = 1 AND CustomerID LIKE @Customer + '%')
OR (IsNumeric(@Customer) = 0 AND CustomerName LIKE @Customer + '%')
但是,您如何搜索具有数字名称的客户?顺便说一下......如果你搜索121
,这样的搜索会找到客户12
。
答案 6 :(得分:1)
SELECT *
FROM dbo.Customers
WHERE ISNUMERIC(@Customer) = 1
AND CustomerID = CAST(@Customer AS INTEGER)
UNION ALL
SELECT *
FROM dbo.Customers
WHERE NOT ISNUMERIC(@Customer) = 1
AND CustomerName LIKE @Customer + '%'
这将使用CustomerID
和CustomerName
答案 7 :(得分:0)
我相信这样做会:
WHERE CustomerID LIKE
CASE WHEN IsNumeric(@Customer) = 1 THEN
CustomerID
ELSE
CustomerName + '%'
END
答案 8 :(得分:0)
哦,就这样做吧....
IF ISNUMERIC(@Customer) THEN
SELECT * FROM .... CustomerID = @Customer
ELSE
SELECT * FROM ... CustomerName LIKE @Customer
但是你想让它更易于维护...
declare @basequery NVARCHAR(4000)
declare @params NVARCHAR(4000)
set @base_query = 'select * from dbo.Customers where '
IF ISNUMERIC(@Customer) THEN
SET @base_query = @base_query + 'customerid = @xCustomer'
SET @params = '@xCustomer int'
END
ELSE
SET @base_query = @base_query + 'customerName LIKE @xCustomer + ''%'' '
SET @params = '@xCustomer nvarchar(1000)'
END
exec sp_execuresql @base_query, @params, @Customer
当然我只会推荐这种动态的sql来进行更复杂的过滤。
答案 9 :(得分:0)
保持简单,每个都有一个索引,在前端确定它是哪一个并设置正确的参数。
CREATE PROCEDURE dbo.getCustomer
(@CustomerID int = null,
@CustomerName VARCHAR(100) = null)
AS
SET NOCOUNT ON
SELECT *
FROM Customers
WHERE CustomerID = @CustomerID
or CustomerName like @CustomerName + '%'