tsql - TSQL 动态查询成视图
问题描述
我正在尝试创建一个能够在任一数据库上运行的动态 sql 查询 - 并将其作为view返回。查询不是问题,那个问题已经解决了。我的问题是我不确定最终如何将其作为视图返回。我尝试将它用作存储过程和表值函数,但到目前为止这两种解决方案都存在问题。
存储过程版本:
CREATE PROCEDURE sp_GetPickSummaryTable
AS
BEGIN
DECLARE @PickSummaryTable TABLE (
COLUMN_A date,
COLUMN_B nvarchar(16),
COLUMN_C int
)
DECLARE @database nvarchar(64)
DECLARE @log_database nvarchar(64)
DECLARE @sql nvarchar(4000)
IF(LEFT(DB_NAME(), 4) = 'log_')
BEGIN
SET @log_database = DB_NAME()
SET @database = SUBSTRING(DB_NAME(), 5, LEN(DB_NAME()) - 4)
END
ELSE
BEGIN
SET @log_database = 'log_' + DB_NAME()
SET @database = DB_NAME()
END
SET @sql = '
SELECT c.COLUMN_A, C.COLUMN_B, pl.COLUMN_C
FROM
' + @log_database + '..PICK_LOG pl
LEFT OUTER JOIN ' + @database + '..[CUSTOM] c ON pl.CUSTOM_NUM = C.CUSTOM_NUM AND pl.COMPANY = c.COMPANY
WHERE pl.[TIMESTAMP] > DATEADD(DAY, -60, GETDATE())
UNION
SELECT c.COLUMN_A, C.COLUMN_B, pl.COLUMN_C
FROM
' + @database + '..PICK_LOG pl
LEFT OUTER JOIN ' + @database + '..[CUSTOM] c ON PL.CUSTOM_NUM = C.CUSTOM_NUM AND pl.COMPANY = c.COMPANY
WHERE pl.[TIMESTAMP] > DATEADD(DAY, -60, GETDATE())'
INSERT INTO @PickSummaryTable ([DATE], CUSTOM_GROUP, CUSTOM_NUM, COMPANY, CUSTOM_DESC, LINES, QTY_SUF, DISTINCT_ORDERS)
EXEC sp_executesql @sql
SELECT [DATE], CUSTOM_GROUP, CUSTOM_NUM, COMPANY, CUSTOM_DESC, LINES, QTY_SUF, DISTINCT_ORDERS
FROM @PickSummaryTable
END
如果在“数据库”或“log_database”上运行,这将正确返回我想要作为视图返回的数据表。但我无法在视图中访问存储过程的结果。
我要创建的视图如下所示:
CREATE VIEW [dbo].[PICK_SUMMARY]
AS
WITH A AS (
EXEC sp_GetPickSummaryTable
)
SELECT * FROM A
表值函数版本:
CREATE FUNCTION fn_GetPickSummaryTable()
RETURNS @PickSummaryTable TABLE (
COLUMN_A date,
COLUMN_B nvarchar(16),
COLUMN_C int
)
AS
BEGIN
DECLARE @database nvarchar(64)
DECLARE @log_database nvarchar(64)
DECLARE @sql nvarchar(4000)
IF(LEFT(DB_NAME(), 4) = 'log_')
BEGIN
SET @log_database = DB_NAME()
SET @database = SUBSTRING(DB_NAME(), 5, LEN(DB_NAME()) - 4)
END
ELSE
BEGIN
SET @log_database = 'log_' + DB_NAME()
SET @database = DB_NAME()
END
SET @sql = '
SELECT c.COLUMN_A, C.COLUMN_B, pl.COLUMN_C
FROM
' + @log_database + '..PICK_LOG pl
LEFT OUTER JOIN ' + @database + '..[CUSTOM] c ON pl.CUSTOM_NUM = C.CUSTOM_NUM AND pl.COMPANY = c.COMPANY
WHERE pl.[TIMESTAMP] > DATEADD(DAY, -60, GETDATE())
UNION
SELECT c.COLUMN_A, C.COLUMN_B, pl.COLUMN_C
FROM
' + @database + '..PICK_LOG pl
LEFT OUTER JOIN ' + @database + '..[CUSTOM] c ON PL.CUSTOM_NUM = C.CUSTOM_NUM AND pl.COMPANY = c.COMPANY
WHERE pl.[TIMESTAMP] > DATEADD(DAY, -60, GETDATE())'
INSERT INTO @PickSummaryTable ([DATE], CUSTOM_GROUP, CUSTOM_NUM, COMPANY, CUSTOM_DESC, LINES, QTY_SUF, DISTINCT_ORDERS)
EXEC sp_executesql @sql
RETURN
END
GO
但这会返回错误,因此我无法创建该函数。
Invalid use of a side-effecting operator 'INSERT EXEC' within a function.
解决方案
视图和函数都不能做exec
任何事情,因此您不能在视图中使用动态 sql(即使您尝试在各个级别的嵌套下隐藏动态)。
然而,一切都没有丢失!有一些聪明的方法可以做你想做的事。
一种方法是动态创建同义词,然后有一个使用这些同义词的静态视图。例如:
create or alter procedure redirect_synonyms (@todb sysname) as begin
drop synonym if exists sys_tables;
declare @sql varchar(200) = concat('create synonym sys_tables for ', quotename(@todb), '.sys.tables')
exec(@sql)
end
exec redirect_synonyms 'msdb';
create or alter view cleverview as select * from sys_tables;
select * from cleverview;
exec redirect_synonyms 'master';
select * from cleverview;
推荐阅读
- reactjs - 反应检查多维数组中的元素而不会中断 - 更好的方法吗?
- javascript - 只读输入的千位分隔符
- javascript - React-Native-Maps:地图为空。仅显示 Google 徽标和标记
- firebase - 反应原生地图方向
- angular - Angular 12.2 导致 Typescript 出现优化问题。所有类型都具有相同的名称并启用了优化
- javascript - 如何保持使用 auth0 登录的 React 应用程序
- vue.js - 无法更新引导 vue 表中的数据
- encryption - 如何从未删除的加密文件中获取原始文件?
- javascript - 在Javascript中从数组中过滤一组字母
- nixos - 创建具有自定义固件支持的可引导 USB