我的存储过程有两个参数。根据{{1}}的值,必须搜索正确的列。在伪代码格式中,它应该是这样的
Searching_Condition
以下是我正在处理的代码以及陷入困境的代码。它应该很简单但是man ...由于不熟悉SQL Server,我很挣扎,SQL Server中的//CASE @Search_Condition
// WHEN 'UserID' THEN SELECT * FROM user_table WHERE UserID LIKE '@Keywords'
// WHEN 'UserName' THEN SELECT * FROM user_table WHERE UserName LIKE '@Keywords'
// WHEN 'UserAddress' THEN SELECT * FROM user_table WHERE UserAddress LIKE '@Keywords'
不能像我想象的那样工作。
谢谢!
CASE
答案 0 :(得分:1)
帮助您做到这一点的关键概念是表达式和语句之间的区别。
声明是程序性的,并指导控制流程。您可以想到一个从语句到语句的指令指针,并且每个语句都与其他语句隔离(尽管它们可以选择执行它们之后的语句)。它们可以被认为是动词。
表达式可以减少为某个值 - 标量值,字符串甚至行集 - 但表达式不会命令执行任何操作。他们可以被认为是名词。这些名词本身不能存在,它们必须在陈述的背景下。
SQL Server中的CASE
语句是表达式。它不是像Select Case
那样的程序语句,例如Visual Basic。诀窍是,当语言需要表达式时,不能替换语句 - 此外,除了在某些特殊用法中,您不能将过程语句放在表达式的中间(除了行集)可以作为表达式进行评估,例如单列和单行SELECT
或EXISTS
)。表达式可以包含包含表达式的表达式。它们就像一棵树,一直倒塌。
考虑EXECUTE dbo.MyStoredProcedure (8 + @@SPID) / 2
中的部分:这是一个单个语句,带有一个参数表达式,由三个子表达式组成,按特定顺序计算,解析为单个值,用作存储过程的参数。您无法单独执行(8 + @@SPID) / 2
,因为它不是声明。 (不要紧,表达式很愚蠢,仅举例来说。)
我确实说过,在某些情况下,行集可以是值,但几乎所有表达式的预期类型都是单个值 - 而不是行集。这就是这里发生的问题 - 您的外SELECT
语句期望单行中第一列定义的单值(因为您没有FROM
子句),但是当您的搜索条件为'user_name'
时,您正尝试提供整个行集。
您可以完全放弃CASE
并使用IF
来解决此问题 - 因为IF
是一个程序性陈述。
CREATE PROCEDURE [dbo].[USP_SP_NAME]
@Searching_Condition NVARCHAR(100),
@Keywords NVARCHAR(100)
AS
SET NOCOUNT ON;
SET LOCK_TIMEOUT 3000;
SET XACT_ABORT ON;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN TRY
IF @Searching_Condition = 'user_id' BEGIN
select count(*) from user_table;
END
ELSE IF @Searching_Condition = 'user_name' BEGIN
select * from user_table;
END;
END TRY;
我主张避免不使用IF
和BEGIN
的{{1}}版本并接受单个声明 - 这种形式会导致混淆和错误。我每次都使用END
和BEGIN
,这看起来很痛苦,直到你发现这样做有多少时间和精力可以帮助你节省时间......
答案 1 :(得分:0)
你可以试试这个,不需要提供案例,条件会根据@Searching_Condition
的值而改变:
CREATE PROCEDURE [dbo].[USP_SP_NAME]
@Searching_Condition NVARCHAR(100),
@Keywords NVARCHAR(100)
AS
SET NOCOUNT ON
SET LOCK_TIMEOUT 3000
SET XACT_ABORT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
BEGIN TRY
exec('Select * from user_table WHERE'+ @Searching_Condition+' LIKE '+ @Keywords);
END TRY