我正在尝试在SQL Server 2005中使用“WITH”语句。如果我执行以下操作,它似乎工作正常:
WITH MyBigProducts AS (SELECT * FROM Products WHERE Size='Big')
SELECT Name FROM MyBigProducts
但如果我尝试使用多个选择语句,它会失败,如:
WITH MyBigProducts AS (SELECT * FROM Products WHERE Size='Big')
SELECT Name FROM MyBigProducts
SELECT Count(*) FROM MyBigProducts
,错误消息为“无效的对象名称'MyBigProducts'”。
我可以采取哪些措施来扩大“MyBigProducts”表的范围以包含两个select语句吗?
我的示例是导致问题的实际代码的简化,所以我并不打算上述简单示例应该工作的可能性以及我的SQL中还有另一个错误。
我尝试在两个SELECT语句周围包装一个BEGIN和END,但解析器无法编译它。
答案 0 :(得分:14)
我相信公用表表达式仅对即时使用有效,这就是“SELECT Count(*)FROM MyBigProducts”出错的原因。为了重用CTE,您应该使用临时表
DECALRE @BigProducts TABLE (...[declaration omitted]...)
INSERT INTO @BigProducts
SELECT *
FROM Products
WHERE Size='Big'
SELECT Name FROM @BigProducts
SELECT Count(*) FROM @BigProducts
如果我错了,请纠正我。
答案 1 :(得分:14)
正如Kane所说,CTE仅在编写它的SQL语句中可用。根据您的具体情况,另一种可能的解决方案是在单个查询中包含COUNT(*):
;WITH MyBigProducts AS
(
SELECT
Name,
COUNT(*) OVER () AS total_count
FROM
Products
WHERE
Size = 'Big'
)
SELECT
Name,
total_count
FROM
MyBigProducts
答案 2 :(得分:2)
CTE具有声明本地范围和可见性。如果您想要更大的表空间范围和可见性,则需要将CTE设置为View或表值函数。
或者,您可以将表达式结果具体化为表变量,该表变量是当前批次的本地变量,或者是临时表,其生命周期也是当前批次的本地,但其可见性扩展到整个会话。
答案 3 :(得分:-1)
WITH n(id, name) AS
(SELECT id, name
FROM ABC
WHERE parent = 44
UNION ALL
SELECT m.id, m.name
FROM ABC as m, n
WHERE n.id = m.parent)
SELECT * FROM n