是否可以将以下代码放入表值(内联或多语句)甚至 View 中。我可以在存储过程中使用它,但由于无法连接存储过程的结果,我宁愿将其放在表值函数或 View 中。
下面是给出我正在寻找的结果的 SQL
DECLARE @ColumnInformation TABLE
(
DatabaseName NVARCHAR(255),
TableSchema NVARCHAR(255),
TableName NVARCHAR(255),
ColumnName NVARCHAR(255),
TableType NVARCHAR(255),
FullyQualifiedTableName NVARCHAR(255),
FullyQualifiedColumnName NVARCHAR(255)
)
INSERT INTO @ColumnInformation
EXECUTE master.sys.sp_MSForEachDB '
IF ''?'' NOT IN (''master'', ''tempdb'', ''msdb'', ''model'', ''ReportServer'', ''ReportServerTempDB'' )
BEGIN
USE [?];
PRINT ''?''
SELECT
T.TABLE_CATALOG AS DatabaseName
,T.TABLE_SCHEMA as TableSchema
,T.TABLE_NAME AS TableName
,C.COLUMN_NAME AS ColumnName
,T.TABLE_TYPE AS TableType
,''['' + T.TABLE_CATALOG + ''].['' + T.TABLE_SCHEMA + ''].['' + T.TABLE_NAME + '']'' AS FullyQualifiedTableName
,''['' + T.TABLE_CATALOG + ''].['' + T.TABLE_SCHEMA + ''].['' + T.TABLE_NAME + ''].['' + C.COLUMN_NAME + '']'' FullyQualifiedColumnName
FROM INFORMATION_SCHEMA.TABLES as t inner join
INFORMATION_SCHEMA.COLUMNS as c on c.table_name = t.table_name
END
'
SELECT *
FROM @ColumnInformation
ORDER BY DatabaseName, TableSchema, TableName, ColumnName
但是,当我尝试将其放入表值函数时,我收到错误
Msg 443, Level 16, State 14, Procedure fGetAllColumnInformation, Line 17
Invalid use of a side-effecting operator 'INSERT EXEC' within a function.
我相信 sp_MSForEachDb 正在生成动态 SQL,但不确定。我依稀记得听说动态SQL不能用在表值函数中。如果是这种情况,无论如何都可以绕过该限制,以便我可以在表值函数或 View 中使用上述代码。
如果上述答案是否定的...有没有办法重写该语句,使其不使用动态 SQL?
我基本上试图将 SQL Server 上每个数据库的所有 INFORMATION_SCHEMA.COLUMNS 的结果合并起来。
最佳答案
如果没有动态 SQL,则无法动态执行此操作(如不提前对所有数据库名称进行硬编码),并且无法在函数中使用动态 SQL。您shouldn't be using sp_MSForEachDB in any case或者,恕我直言,using INFORMATION_SCHEMA .
编写一个返回结果集的存储过程。如果您绝对需要将输出连接到其他内容(为什么不将其编码到存储过程中?),则将输出插入到 #temp 表中。
试试这个:
CREATE PROCEDURE dbo.AllMyColumnsEverywhereForReals
AS
BEGIN
SET NOCOUNT ON;
DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql += '
UNION ALL SELECT
[database] = N''' + d.name + ''' COLLATE SQL_Latin1_General_CP1_CI_AI,
[schema] = s.name COLLATE SQL_Latin1_General_CP1_CI_AI,
[object] = o.name COLLATE SQL_Latin1_General_CP1_CI_AI,
[column] = c.name COLLATE SQL_Latin1_General_CP1_CI_AI,
[qualified] = QUOTENAME(''' + d.name + ''')
+ ''.'' + QUOTENAME(s.name)
+ ''.'' + QUOTENAME(c.name) COLLATE SQL_Latin1_General_CP1_CI_AS,
[type] = CASE o.type WHEN ''U'' THEN ''Table'' ELSE ''View'' END
FROM ' + QUOTENAME(d.name) + '.sys.columns AS c
INNER JOIN ' + QUOTENAME(d.name) + '.sys.objects AS o
ON c.[object_id] = o.[object_id]
INNER JOIN ' + QUOTENAME(d.name) + '.sys.schemas AS s
ON o.[schema_id] = s.[schema_id]
WHERE o.type IN (''U'', ''V'')'
FROM sys.databases AS d WHERE [state] = 0 AND name NOT IN
(N'master',N'tempdb',N'msdb',N'model',N'ReportServer',N'ReportServerTempDB');
SET @sql = STUFF(@sql, 1, 13, '');
EXEC sp_executesql @sql;
END
GO
用法:
CREATE TABLE #x
(
db SYSNAME,
sch SYSNAME,
obj SYSNAME,
col SYSNAME,
qual NVARCHAR(390),
[type] CHAR(5)
);
INSERT #x EXEC dbo.AllMyColumnsEverywhereForReals;
SELECT cols FROM #x AS x -- INNER JOIN something else ON x.whatever...
关于sql - sp_MSForEachDB 在函数内无效使用副作用运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17840506/