【问题标题】:How can I use if statement after a CTE (SQL Server 2005)如何在 CTE (SQL Server 2005) 之后使用 if 语句
【发布时间】:2009-10-13 03:42:43
【问题描述】:

昨晚我在写一个类似这样的简单 T-SQL 程序

DECLARE @ROLEID AS INT

SELECT @ROLEID = [ROLE ID] FROM TBLROLE

;WITH CTE
AS
( 
    SELECT * FROM SOMETABLE
)
IF (@ROLEID  = 1) 
BEGIN
      //SOMECODE
END
ELSE IF(@ROLEID  = 2) 
BEGIN
      //SOMECODE
END
ELSE
BEGIN 
      //SOMECODE
END

我在编译后发现它会抛出类似“Incorrect statement near if”之类的错误

怎么了?

但是,我通过其他方式做到了这一点。但我想知道为什么它不起作用!

【问题讨论】:

  • 在每种情况下 //SOMECODE 的作用是什么?例如,如果它们都是针对同一个表的 UPDATE 语句,那么您可以使用 @ROLEID 变量省略过程代码,而是使用基于集合的方法编写单个 UPDATE。
  • 其实我是在选择像 select * from tblname 这样的记录。没有任何 dml 操作
  • 改用临时表

标签: sql sql-server sql-server-2005 tsql common-table-expression


【解决方案1】:

Common table expressions 在单个语句的上下文中定义:

WITH cte_name AS (
  <cte definition>)
<statement that uses cte>;

所以你可以这样做:

WITH CTE
AS
( 
    SELECT * FROM SOMETABLE
)
SELECT * FROM CTE;

WITH CTE
AS
( 
    SELECT * FROM SOMETABLE
)
UPDATE CTE 
SET somefield = somevalue
WHERE id = somekey;

CTE 后面必须跟一个 选择、插入、更新、合并或 引用一些的 DELETE 语句 或所有 CTE 列。 CTE 也可以 在 CREATE VIEW 中指定 声明作为定义的一部分 视图的SELECT语句

【讨论】:

  • 您可以在 WITH CTE AS ( ) 之后立即使用 SELECT * INTO #TempTable FROM CTE ,然后使用 IF .... ELSE .... 它可以从 #TempTable 中为 IF 中的条件列值,否则。
【解决方案2】:

最接近的方法是使用 UNION ALL 进行粗略的切换选择:

DECLARE @ROLEID AS INT

SELECT @ROLEID = [ROLE ID] FROM TBLROLE

;WITH CTE
AS
( 
    SELECT * FROM SOMETABLE
)
SELECT
    --somecolumns
FROM
    CTE
    --other stuff too
WHERE
    @ROLEID = 1
UNION ALL
SELECT
    --somecolumns
FROM
    CTE
    --other stuff too
WHERE
    @ROLEID = 2
UNION ALL
SELECT
    --somecolumns
FROM
    CTE
    --other stuff too
WHERE
    @ROLEID = 3
...
UNION ALL
SELECT
    --somecolumns
FROM
    CTE
    --other stuff too
WHERE
    @ROLEID = n

【讨论】:

  • 在这种情况下,列需要相同。我有一个列不同的情况。仍在寻找解决方案
【解决方案3】:

有点晚了,但我不会是唯一一个碰到这个的人。

一种解决方案可能是像这样创建一个临时表:

-- If previous run of this query fails, the temp table will be deleted.
-- Selecting into creates the temp table which fails if it already exists
IF EXISTS(SELECT [name] FROM tempdb.sys.tables WHERE [name] like '#dtBalansOpgesteldGefilterd%') BEGIN
   DROP TABLE #temp
END;

;WITH CTE
AS
( 
    SELECT * FROM SOMETABLE
)

-- Followed by select statement as required
SELECT *
INTO #temp
FROM CTE

IF @awsome = 1
BEGIN
    SELECT 'WHATEVERYOUWANT' AS WhateverColumnNameYouWant, *
    FROM #temp
END

【讨论】:

  • 建议我将整个内容包装在BEGIN TRANSACTION; CREATE TABLE #temp; [entire thing]; DROP TABLE #temp; COMMIT 中,而不是检查表是否存在,并且它工作得更好一些,因为它消除了删除临时表所需的特殊权限的问题。
【解决方案4】:

尝试将 CTE 放在 IF 中。它对我有用。

IF @awsome = 1
BEGIN
;WITH CTE
AS
( 
    SELECT * FROM SOMETABLE
)
    SELECT 'WHATEVERYOUWANT' FROM CTE
END
ELSE IF @awesome = 2
BEGIN
;WITH CTE2
AS
( 
    SELECT * FROM SOMETABLE
)
    SELECT 'WHATEVERYOUWANT' FROM CTE2
END

【讨论】:

  • 如果 CTE(或 CTE)很复杂,这会导致大量重复的 SQL。然后你必须解决 IF 的两个分支中的任何问题。
猜你喜欢
  • 2013-02-01
  • 1970-01-01
  • 2022-11-22
  • 1970-01-01
  • 2013-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多