视图 SQL 服务器中临时 Table 的解决方法
Workaround for temporary Table in view SQL Server
我遇到以下问题:我想创建一个视图,其中包含 table,其列 'verylongtext' 应拆分为不得超过 50 个字符的字符串。
此结果集应加入视图中。
临时 table 将按以下方式创建:
create table #results(id int, string varchar(400))
declare @results table(id int, string varchar(400))
declare @id int
declare @strings varchar(400)
set @id = 0
while exists (select * from roottable where row_id > @id)
begin
select top 1 @id = row_id, @strings = verylongtext from roottable
where row_id > @id
order by row_id asc
insert into #results
select @id, data from dbo.Split( [dbo].[DelineateEachNth](@strings, 50, '$'), '$')
end
问题当然是视图中不允许临时 table。 CTE 似乎不适用于函数的结果集。还有其他可能的方法吗?我完全无能为力。提前致谢!!
您可以使用 APPLY
在基础 table 上直接调用拆分函数,这意味着不需要临时 table 或循环:
SELECT r.id, s.data
FROM RootTable AS r
CROSS APPLY dbo.Split(dbo.DelineateEachNth(r.VeryLongText, 50, '$'), '$') AS s;
您可能会发现标量函数 dbo.DelineateEachNth
是性能杀手(因为所有标量 UDF 都是如此),因此拆分字符串的另一种方法是使用计数 table:
CREATE FUNCTION dbo.FixedLengthSplit
(
@String NVARCHAR(MAX),
@Length INT
)
RETURNS TABLE
WITH SCHEMABINDING AS
RETURN
( WITH N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1), (1)) n (N)),
N2(N) AS (SELECT 1 FROM N1 a CROSS JOIN N1 b),
N3(N) AS (SELECT 1 FROM N2 a CROSS JOIN N2 b),
N4(N) AS (SELECT 1 FROM N3 a CROSS JOIN N3 b),
Numbers (N) AS
( SELECT TOP (CONVERT(INT, CEILING(1.0 * ISNULL(LEN(@String),1) / @Length)))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
FROM n4
)
SELECT ItemNumber = N + 1,
Data = SUBSTRING(@String, 1 + (@Length * N), @Length)
FROM Numbers
);
那么你的观点就是:
SELECT *
FROM rootTable AS r
CROSS APPLY dbo.FixedLengthSplit(r.VeryLongString, 50) AS s;
我遇到以下问题:我想创建一个视图,其中包含 table,其列 'verylongtext' 应拆分为不得超过 50 个字符的字符串。 此结果集应加入视图中。 临时 table 将按以下方式创建:
create table #results(id int, string varchar(400))
declare @results table(id int, string varchar(400))
declare @id int
declare @strings varchar(400)
set @id = 0
while exists (select * from roottable where row_id > @id)
begin
select top 1 @id = row_id, @strings = verylongtext from roottable
where row_id > @id
order by row_id asc
insert into #results
select @id, data from dbo.Split( [dbo].[DelineateEachNth](@strings, 50, '$'), '$')
end
问题当然是视图中不允许临时 table。 CTE 似乎不适用于函数的结果集。还有其他可能的方法吗?我完全无能为力。提前致谢!!
您可以使用 APPLY
在基础 table 上直接调用拆分函数,这意味着不需要临时 table 或循环:
SELECT r.id, s.data
FROM RootTable AS r
CROSS APPLY dbo.Split(dbo.DelineateEachNth(r.VeryLongText, 50, '$'), '$') AS s;
您可能会发现标量函数 dbo.DelineateEachNth
是性能杀手(因为所有标量 UDF 都是如此),因此拆分字符串的另一种方法是使用计数 table:
CREATE FUNCTION dbo.FixedLengthSplit
(
@String NVARCHAR(MAX),
@Length INT
)
RETURNS TABLE
WITH SCHEMABINDING AS
RETURN
( WITH N1 AS (SELECT N FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1), (1)) n (N)),
N2(N) AS (SELECT 1 FROM N1 a CROSS JOIN N1 b),
N3(N) AS (SELECT 1 FROM N2 a CROSS JOIN N2 b),
N4(N) AS (SELECT 1 FROM N3 a CROSS JOIN N3 b),
Numbers (N) AS
( SELECT TOP (CONVERT(INT, CEILING(1.0 * ISNULL(LEN(@String),1) / @Length)))
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1
FROM n4
)
SELECT ItemNumber = N + 1,
Data = SUBSTRING(@String, 1 + (@Length * N), @Length)
FROM Numbers
);
那么你的观点就是:
SELECT *
FROM rootTable AS r
CROSS APPLY dbo.FixedLengthSplit(r.VeryLongString, 50) AS s;