我试图从Stackoverflow线程中理解这个查询:
--create test table
CREATE TABLE dbo.TestTable(
Col1 nchar(4000) NOT NULL
, Col2 nvarchar(MAX) NOT NULL
);
--load 10000 rows (about 2.8GB)
WITH
t4 AS (SELECT n FROM (VALUES(0),(0),(0),(0)) t(n))
,t256 AS (SELECT 0 AS n FROM t4 AS a CROSS JOIN t4 AS b CROSS JOIN t4 AS c CROSS JOIN t4 AS d)
,t16M AS (SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) AS num FROM t256 AS a CROSS JOIN t256 AS b CROSS JOIN t256 AS c)
INSERT INTO dbo.TestTable WITH(TABLOCKX) (Col1, Col2)
SELECT REPLICATE(N'X', 4000), REPLICATE(CAST('X' AS nvarchar(MAX)), 10000)
FROM t16M
WHERE num <= 100000;
GO
--run query in loop (expect parallel execution plan with many read-ahead and LOB page reads)
SET NOCOUNT ON;
DECLARE @RowCount int, @Iteration int = 1;
WHILE @Iteration <= 100
BEGIN
CHECKPOINT;
DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS;
SELECT @RowCount = COUNT(*) FROM dbo.TestTable WHERE Col2 LIKE 'X%';
RAISERROR('Iteration %d completed',0,1,@Iteration) WITH NOWAIT; --display progress message
SET @Iteration += 1;
END;
GO
我特别无法理解t-sql查询的这一部分:
--load 10000 rows (about 2.8GB)
WITH
t4 AS (SELECT n FROM (VALUES(0),(0),(0),(0)) t(n))
,t256 AS (SELECT 0 AS n FROM t4 AS a CROSS JOIN t4 AS b CROSS JOIN t4 AS c CROSS JOIN t4 AS d)
,t16M AS (SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) AS num FROM t256 AS a CROSS JOIN t256 AS b CROSS JOIN t256 AS c)
INSERT INTO dbo.TestTable WITH(TABLOCKX) (Col1, Col2)
SELECT REPLICATE(N'X', 4000), REPLICATE(CAST('X' AS nvarchar(MAX)), 10000)
FROM t16M
WHERE num <= 100000;
GO
为什么我们有&#34; With&#34;在&#34; - 加载10000rows ...&#34; ;这是什么&#34;与&#34;做?它是&#39;创造&#39;的一部分?声明?
关于此插入声明:
INSERT INTO dbo.TestTable WITH(TABLOCKX) (Col1, Col2)
SELECT REPLICATE(N'X', 4000), REPLICATE(CAST('X' AS nvarchar(MAX)), 10000)
FROM t16M
WHERE num <= 100000;
不会
INSERT INTO dbo.TestTable WITH(TABLOCKX) (Col1, Col2)
FROM t16M
WHERE num <= 100000;
做什么?以上不会从t16M获取前10000行并插入dbo.TestTable吗?为什么我们这样做&#34;选择...&#34;?这意味着什么?
我了解REPLICATE(N'X', 4000)
X
将Col1
REPLICATE(CAST('X' AS nvarchar(MAX)), 10000)
X
Col2
{{1}} {{1}} {{1}} {{1}}。如果我们这样做,为什么选择t16M?或者如果我们从t16M中选择,那么为什么这会复制呢?
是什么 @RowCount = COUNT(*) 做?将表中的行数分配给名为&#39; RowCount&#39;的变量是否与&#39; @@ RowCount&#39;?相同?我不认为可以。
答案 0 :(得分:3)
我会重新格式化代码以便更好地理解:
WITH t4 AS(
SELECT n FROM (VALUES(0),(0),(0),(0)) t(n)
)
,t256 AS(
SELECT 0 AS n
FROM t4 AS a
CROSS JOIN t4 AS b
CROSS JOIN t4 AS c
CROSS JOIN t4 AS d
)
,t16M AS(
SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) AS num
FROM t256 AS a
CROSS JOIN t256 AS b
CROSS JOIN t256 AS c
)
INSERT INTO dbo.TestTable WITH(TABLOCKX) (Col1, Col2)
SELECT REPLICATE(N'X', 4000), REPLICATE(CAST('X' AS nvarchar(MAX)), 10000)
FROM t16M
WHERE num <= 100000;
3个级联CTE
组成了Tally Table
或其他名为Numbers Table
的人。它由从1到某个数字的序号组成。
这个生成4行,值为0:
WITH t4 AS(
SELECT n FROM (VALUES(0),(0),(0),(0)) t(n)
)
然后它CROSS JOIN
自身4次,从而生成4 * 4 * 4 * 4
或4^4
或256
行,因此生成别名t256
。同样t256
CROSS JOIN
为自己3次,产生16,777,216
行,因此产生别名t16M
。
如果您执行SELECT * FROM t16M
,则可以验证它是否返回超过16M的行。
然后使用它将100000行插入TestTable
,如where子句所示:
INSERT INTO dbo.TestTable WITH(TABLOCKX) (Col1, Col2)
SELECT REPLICATE(N'X', 4000), REPLICATE(CAST('X' AS nvarchar(MAX)), 10000)
FROM t16M
WHERE num <= 100000
有些人可能会使用WHILE
循环来尝试执行此操作,即在表中插入100000行。 Tally Table
是以基于集合的方式执行此操作的好方法。有关详细信息,请阅读:http://www.sqlservercentral.com/articles/T-SQL/62867/
问题#2
WITH
语句下方的CREATE
关键字标记Common Table Expression的声明。
问题#3 我相信下面的查询会产生语法错误。
INSERT INTO dbo.TestTable WITH(TABLOCKX) (Col1, Col2)
FROM t16M
WHERE num <= 100000;
另一方面,这不会。
INSERT INTO dbo.TestTable WITH(TABLOCKX) (Col1, Col2)
SELECT REPLICATE(N'X', 4000), REPLICATE(CAST('X' AS nvarchar(MAX)), 10000)
FROM t16M
WHERE num <= 100000;
此查询的作用是INSERT
100000行,由2列组成,其值为'X'的连续字符串。请记住,t16M
是我们的Tally Table
,其中包含从1到16M +的数字序列。我们不对插入使用Tally Table
的值,我们只使用其行的存在来限制插入的数量。
问题#4 当你说@RowCount = COUNT(*)
为变量分配行数时,你是对的。
SELECT @RowCount = COUNT(*) FROM dbo.TestTable WHERE Col2 LIKE 'X%';
SELECT @@ROWCOUNT
但是,上述说法并不相同。 @@ROWCOUNT返回受最后一个语句影响的行数。如果我们将其放在WHILE
之后的SELECT @RowCount
循环中,它将返回1,因为只有1行受到影响。但是,如果我们将其直接放在INSERT
语句之后,它将返回与SELECT COUNT(*) FROM dbo.TestTable
相同的内容。