【发布时间】:2009-05-27 18:59:02
【问题描述】:
在 sysobjects 上进行选择时如何获取 SCHEMA?
我正在修改一个名为 SearchObjectsForText 的存储过程,它只返回名称,但我还想包含 SCHEMA。
现在它正在做类似的事情:
SELECT DISTINCT name
FROM sysobjects
我想知道需要连接哪些表才能返回每个“名称”的 SCHEME。
【问题讨论】:
标签: sql sql-server tsql
在 sysobjects 上进行选择时如何获取 SCHEMA?
我正在修改一个名为 SearchObjectsForText 的存储过程,它只返回名称,但我还想包含 SCHEMA。
现在它正在做类似的事情:
SELECT DISTINCT name
FROM sysobjects
我想知道需要连接哪些表才能返回每个“名称”的 SCHEME。
【问题讨论】:
标签: sql sql-server tsql
如果您指的是 SQL Server 2005 或更高版本,请使用 sys.objects 而不是 sysobjects:
SELECT sys.objects.name, sys.schemas.name AS schema_name
FROM sys.objects
INNER JOIN sys.schemas ON sys.objects.schema_id = sys.schemas.schema_id
2005 年引入了模式。最多 2000 个,用户等于模式。 SQL Server 2000 的相同查询:
SELECT sysusers.name AS OwnerName, sysobjects.name
FROM sysobjects
INNER JOIN sysusers ON sysobjects.uid = sysusers.uid
【讨论】:
在 Sql Server 2005(及更高版本)上,您可以使用 sys.objects 视图:
select
name as ObjectName,
schema_Name(schema_id) as SchemaName
from
sys.objects
在 Sql Server 2000(及以下)中,“模式”具有不同的概念含义。来自 MSDN 的注释:
在 SQL Server 的早期版本中,数据库可能包含称为“模式”的实体,但该实体实际上是数据库用户。 SQL Server 2005 是 SQL Server 的第一个版本,其中架构既是容器又是命名空间。
【讨论】:
你能改用Information_Schema view(s)吗?
SELECT DISTINCT table_name, table_schema
FROM INFORMATION_SCHEMA.TABLES
根据the MSDN page(适用于 SQL Server 2008 及更高版本),
不要使用 INFORMATION_SCHEMA 视图来确定对象的架构。查找对象架构的唯一可靠方法是查询 sys.objects 目录视图。
但是,似乎他们可能指的是您有一个表名并试图找到它的架构的问题,如果有多个同名的表(在不同的架构中),这将不起作用。如果您要查询多个结果(而不仅仅是尝试查找特定表的架构),那么应该没问题。
【讨论】:
我倾向于使用更集中的“sys”视图 - sys.procedures 而不是 sys.objects。您需要将其与 sys.schemas 视图结合以获取架构名称等。
select
p.name,
s.name 'Schema',
p.type_desc, p.create_date, p.modify_date
from
sys.procedures p
inner join
sys.schemas s ON p.schema_id = s.schema_id
我将开始不再使用“sysobjects”,因为 Microsoft 在联机丛书中明确指出“sysobjects”将在未来的版本中被删除:
此 SQL Server 2000 系统表作为视图包含在内以实现向后兼容性。我们建议您改用当前的 SQL Server 系统视图。要查找等效的系统视图,请参阅将 SQL Server 2000 系统表映射到 SQL Server 2005 系统视图。此功能将在 Microsoft SQL Server 的未来版本中删除。避免在新的开发工作中使用此功能,并计划修改当前使用此功能的应用程序。
马克
【讨论】:
只是重复这里已经建议的内容,这是我使用的,在我的数据库中获取表、存储过程、视图和函数的列表:
SELECT schema_Name(schema_id) as SchemaName,
[name], -- Name of the Table, Stored Procedure or Function
[type] -- 'V' for Views, 'U' for Table, 'P' for Stored Procedure, 'FN' for function
FROM sys.objects
WHERE [type_desc] IN ( 'USER_TABLE', 'SQL_STORED_PROCEDURE', 'VIEW', 'SQL_SCALAR_FUNCTION')
AND [name] NOT LIKE 'sp_%'
AND [name] NOT LIKE 'fn_%'
ORDER BY 3 DESC, -- type first
1 ASC, -- then schema
2 ASC -- then function/table name
...这就是我们的好朋友 Northwind 将返回的东西...
【讨论】:
在 SQL 200 中:
select DISTINCT
name as ObjectName,
USER_NAME(uid) as SchemaName
from
sysobjects
在 SQL Server 的早期版本中,数据库可能包含称为“模式”的实体,但该实体实际上是数据库用户。
【讨论】:
包含一个选项,可以删除以特定前缀开头的所有对象,也可以从特定模式中删除。 顺便说一句,我添加了额外的查询来获取默认情况下未存储在 sysobjects 上的所有类型。
我已将整个示例脚本上传到 GitHub: DropAll_Dnn_Objects.sql
第 1 部分:临时存储过程:
IF OBJECT_ID('_temp_DropAllDnnObjects') IS NOT NULL
DROP PROCEDURE _temp_DropAllDnnObjects;
GO
CREATE PROCEDURE _temp_DropAllDnnObjects
@object_prefix NVARCHAR(30),
@schema_name sysname = NULL
AS
BEGIN
DECLARE @sname sysname, @name sysname, @type NVARCHAR(30)
DECLARE @object_type NVARCHAR(255), @sql NVARCHAR(2000), @count INT = 0
DECLARE curs CURSOR FOR
SELECT sname, [name], xtype
FROM (
SELECT SCHEMA_NAME(schema_id) as sname, [name], [type] as xtype
FROM sys.objects
WHERE [type] IN ('U', 'P', 'FN', 'IF', 'TF', 'V', 'TR')
AND name LIKE @object_prefix + '%'
AND (@schema_name IS NULL OR schema_id = SCHEMA_ID(@schema_name))
UNION ALL
SELECT SCHEMA_NAME(schema_id) as sname, [name], 'TYPE' as xtype
FROM sys.types
WHERE is_user_defined = 1
AND [name] LIKE @object_prefix + '%'
AND (@schema_name IS NULL OR schema_id = SCHEMA_ID(@schema_name))
) a
ORDER BY CASE xtype
WHEN 'P' THEN 1
WHEN 'FN' THEN 2
WHEN 'IF' THEN 3
WHEN 'TF' THEN 4
WHEN 'TR' THEN 5
WHEN 'V' THEN 6
WHEN 'U' THEN 7
WHEN 'TYPE' THEN 8
ELSE 9
END, name
OPEN curs;
FETCH NEXT FROM curs INTO @sname, @name, @type;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @count = @count + 1
-- Configuration point 2
SET @object_type = CASE @type
WHEN 'P' THEN 'PROCEDURE'
WHEN 'FN' THEN 'FUNCTION'
WHEN 'IF' THEN 'FUNCTION'
WHEN 'TF' THEN 'FUNCTION'
WHEN 'TR' THEN 'TRIGGER'
WHEN 'V' THEN 'VIEW'
WHEN 'U' THEN 'TABLE'
WHEN 'TYPE' THEN 'TYPE'
END
SET @sql = REPLACE(REPLACE(REPLACE('DROP <TYPE> [<SCHEMA>].[<NAME>];',
'<TYPE>', @object_type),
'<SCHEMA>', @sname),
'<NAME>', @name)
BEGIN TRY
PRINT @sql
EXEC(@sql)
END TRY
BEGIN CATCH
PRINT 'ERROR: ' + ERROR_MESSAGE()
END CATCH
FETCH NEXT FROM curs INTO @sname, @name, @type;
END;
PRINT CONCAT('Objects Found: ', @Count)
PRINT ''
PRINT '------------------------------------------------------'
PRINT ''
CLOSE curs;
DEALLOCATE curs;
RETURN @Count
END;
GO
它会继续出错(并显示错误消息)。它将返回找到的所有对象的计数。
第 2 部分:使用参数调用存储过程:
您可以创建一个 WHILE 循环来运行命令,直到没有留下任何对象(依赖项),如下所示:
DECLARE @count INT = 1
WHILE @count > 0 EXEC @count = _temp_DropAllDnnObjects 'dnn';
SET @count = 1
WHILE @count > 0 EXEC @count = _temp_DropAllDnnObjects 'aspnet';
SET @count = 1
WHILE @count > 0 EXEC @count = _temp_DropAllDnnObjects 'vw_aspnet';
GO
第 3 部分:最后,摆脱程序:
IF OBJECT_ID('_temp_DropAllDnnObjects') IS NOT NULL
DROP PROCEDURE _temp_DropAllDnnObjects;
GO
【讨论】:
为什么不使用它来填充您可以使用的临时表,而不是视图?
这是我在存储过程中使用的解决方案
这是动态获取架构并将其添加到数据库中的不同表以便动态获取其他信息的最佳方式
select @sql = 'insert #tables SELECT ''[''+SCHEMA_NAME(schema_id)+''.''+name+'']'' AS SchemaTable FROM sys.tables'
exec (@sql)
当然#tables是存储过程中的动态表
【讨论】: