2009-05-27 19 views
26

¿Cómo obtengo el SCHEMA al hacer una selección en sysobjects?Servidor SQL - Esquema de retorno para sysobjects

Estoy modificando un procedimiento almacenado llamado SearchObjectsForText que devuelve solo el Nombre pero también me gustaría incluir el SCHEMA.

En este momento se está haciendo algo similar a esto:

SELECT DISTINCT name 
FROM sysobjects 

Me gustaría saber qué tablas tienen que estar unidos para devolver el esquema para cada uno 'nombre'.

Respuesta

53

Si se refiere a SQL Server 2005 o superior, utilice sys.objects en lugar de 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 introdujeron esquemas. hasta 2000, los usuarios igualaron los esquemas. La misma consulta para SQL Server 2000:

SELECT sysusers.name AS OwnerName, sysobjects.name 
FROM sysobjects 
INNER JOIN sysusers ON sysobjects.uid = sysusers.uid 
+0

Debido al diseño del procedimiento almacenado SearchObjectsForText, terminé usando este método. Pero también me gustó la "ciencia del cable" porque era mucho más simple. –

+0

Vale la pena señalar que esto * no * dará los mismos resultados. Por ejemplo, sysobjects devolverá las vistas del catálogo del sistema mientras que sys.objects no lo hace. –

4

Podría utilizar el Information_Schema view(s) en su lugar?

SELECT DISTINCT table_name, table_schema 
FROM INFORMATION_SCHEMA.TABLES 

Según the MSDN page (para SQL Server 2008 y superior),

No utilice vistas INFORMATION_SCHEMA para determinar el esquema de un objeto. La única forma confiable de encontrar el esquema de un objeto es consultar la vista del catálogo sys.objects.

Sin embargo, parece que están probablemente en referencia a un problema que usted tiene un nombre de tabla y están tratando de encontrar su esquema, que no funcionaría si hubo múltiples tablas con el mismo nombre (en diferente esquemas). Si está buscando resultados múltiples (no solo tratando de encontrar el esquema para una tabla específica), entonces debería estar bien.

+0

Ojalá pudiera, pero no quiero cambiar el procedimiento almacenado existente a mucho y simplemente hacer una unión sería más fácil. Gracias por la sugerencia de todos modos. Te di una votación positiva. :) –

+6

¿No utiliza las vistas INFORMATION_SCHEMA para determinar el esquema de un objeto? ¡Voto! Para mí, esto suena como un error que debe corregirse, no como una función que está documentada en MSDN. Si está de acuerdo, asegúrese de enviar sus comentarios en el sitio de MSDN. –

+1

@Alex Estoy absolutamente seguro de que "determinar el esquema de un objeto" significa, dado un nombre de tabla (o id. De objeto), averiguar cuál es su esquema. Y sí, no es confiable hacer esto con las vistas INFORMATION_SCHEMA porque las vistas de information_schema no exponen el ID del objeto y, conociendo solo el nombre de la tabla, puede haber muchas tablas con ese nombre, bajo muchos esquemas. Si solo está enumerando la lista de objetos con sus esquemas y nombres, es completamente seguro usar las vistas INFORMATION_SCHEMA. Tenga en cuenta que puede usar funciones del sistema en identificadores de objeto para devolver nombres de esquema también. – ErikE

14

en SQL Server 2005 (y superior) puede utilizar las sys.objects Vista:

select 
    name     as ObjectName,  
    schema_Name(schema_id) as SchemaName 
from 
    sys.objects 

en SQL Server 2000 (y más adelante), "esquema" tenía un significado conceptual diferente. Nota de MSDN:

En versiones anteriores de SQL Server, las bases de datos podían contener una entidad llamada "esquema", pero esa entidad era efectivamente un usuario de base de datos. SQL Server 2005 es la primera versión de SQL Server en la que un esquema es tanto un contenedor como un espacio de nombres.

3

Yo preferiría utilizar las vistas más centradas del "sys" - sys.procedures en lugar de sys.objects. Deberá unirlo con la vista sys.schemas para obtener el nombre del esquema y demás.

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 

me gustaría empezar a alejarse de usar "sysobjects" desde que Microsoft afirma claramente en los libros en que "sysobjects" es objeto de expulsión en una versión futura:

tabla del sistema Esta SQL Server 2000 es incluido como una vista para la compatibilidad con versiones anteriores. Le recomendamos que use las vistas actuales del sistema del Servidor SQL. Para buscar la vista del sistema o vistas equivalentes, consulte Asignación de tablas del sistema de SQL Server 2000 a vistas del sistema de SQL Server 2005. Esta característica se eliminará en una versión futura de Microsoft SQL Server.Evite usar esta característica en nuevos trabajos de desarrollo y planee modificar las aplicaciones que actualmente usan esta característica.

Marc

+0

Gracias por la idea. Es un procedimiento bastante grande pero que tendrá que ser revisado. Está utilizando todas las vistas antiguas del sistema. –

0

En SQL 200:

select DISTINCT 
    name   as ObjectName,  
    USER_NAME(uid) as SchemaName 
from 
    sysobjects 

En versiones anteriores de SQL Server, bases de datos podría contener una entidad llamada un "esquema", pero esa entidad era efectivamente un usuario de base de datos.

1

Sólo para repetir lo que ya se ha sugerido aquí, aquí es lo que he usado, para obtener una lista de tablas, procedimientos almacenados, vistas y funciones en mi base de datos:

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 

... y esto es lo nuestro buen amigo Neptuno volvería ...

enter image description here

0

han incluido una opción para eliminar todos los objetos a partir de determinado prefijo y, opcionalmente, de ser cierto esquema. Por cierto, agregué consultas adicionales para obtener todos los tipos que no están almacenados en sysobjects por defecto.

He subido toda script de ejemplo para GitHub: DropAll_Dnn_Objects.sql

Parte 1: Temporal procedimiento almacenado:

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 

Continuará en los errores (y mostrar el mensaje de error). Devolverá un recuento de todos los objetos encontrados.

Parte 2: Llamada de procedimiento almacenado con parámetros:

Puede crear un bucle while con el fin de ejecutar el comando hasta que ningún objeto se deja (dependencias), de la siguiente manera:

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 

Parte 3 : Por último, deshágase del procedimiento:

IF OBJECT_ID('_temp_DropAllDnnObjects') IS NOT NULL 
    DROP PROCEDURE _temp_DropAllDnnObjects; 
GO 
Cuestiones relacionadas