2010-05-14 6 views
5

Tengo un servidor con una aplicación de proveedor que depende en gran medida de la base de datos. Necesito hacer algunos cambios menores a los datos en algunas tablas en la base de datos de manera automatizada. Solo INSERTES y ACTUALIZACIONES, nada lujoso. Vendedores como vendedores, nunca puedo estar seguro de cuándo cambian el esquema de una base de datos durante la actualización.¿Cómo puedo introspectar en un servidor SQL?

Para este fin, ¿cómo le pregunto al servidor SQL, de manera scriptable, "Oye, ¿esta tabla aún existe? Sí, genial, está bien, pero ¿tiene esta columna? ¿Cuál es el tipo y tamaño de datos en ¿Es nullable? ¿Podría darme una lista de tablas? En esta tabla, ¿podría darme una lista de columnas? ¿Hay alguna clave primaria allí? No necesito hacer esto para todo el esquema, solo una parte, solo una revisión rápida de la base de datos antes de lanzarme a las cosas.

Actualmente tenemos Microsoft SQL Server 2005, pero podría pasar fácilmente a Microsoft SQL Server 2008. Probablemente no esté utilizando la terminología correcta al realizar la búsqueda. Sé que ORM no solo es demasiado sobrecargado para este tipo de cosas, sino también que no tengo ninguna posibilidad de presentarlo a mis compañeros de trabajo.

Respuesta

5

Ejecutar una consulta como la lista a continuación, a partir de ella se puede ver:

  • esquema nombre
  • nombre de tabla/vista
  • tipo de tabla (como: SYSTEM_TABLE, VIEW, SQL_TABLE_VALUED_FUNCTION, USER_TABLE, SQL_INLINE_TABLE_VALUED_FUNCT ION, INTERNAL_TABLE)
  • nombre de la columna
  • columna de tipo de datos (incluyendo longitud, precisión, etc)
  • Anulabilidad
  • la posición de esta columna en la clave principal
  • completa clave principal, todas las columnas de PK concatenan juntos, si esta columna es parte de la PK
  • de identidad (semilla, incremento y valor actual)
  • cheque definición de restricción
  • defini columnas calculadas ción

Necesidades de SQL Server 2005 + para funcionar:

--optional, remove comments on WHERE to use these 
--DECLARE @SchemaNameSearch sysname 
--  ,@TableNameSearch sysname 
--  ,@ColumnNameSearch sysname 
--SELECT @SchemaNameSearch ='YourSchemaName' 
--  ,@TableNameSearch ='YourTableName' 
--  ,@ColumnNameSearch ='YourColumnName' 

SELECT 
    sh.name+'.'+o.name AS ObjectName 
     ,o.type_desc AS ObjectType 
     ,s.name as ColumnName 
     ,CASE 
      WHEN t.name IN ('char','varchar') THEN t.name+'('+CASE WHEN s.max_length<0 then 'MAX' ELSE CONVERT(varchar(10),s.max_length) END+')' 
      WHEN t.name IN ('nvarchar','nchar') THEN t.name+'('+CASE WHEN s.max_length<0 then 'MAX' ELSE CONVERT(varchar(10),s.max_length/2) END+')' 
      WHEN t.name IN ('numeric') THEN t.name+'('+CONVERT(varchar(10),s.precision)+','+CONVERT(varchar(10),s.scale)+')' 
      ELSE t.name 
     END AS DataType 

     ,CASE 
      WHEN s.is_nullable=1 THEN 'NULL' 
      ELSE 'NOT NULL' 
     END AS Nullable 
     ,xc.key_ordinal AS PK_Position 
     ,CASE 
      WHEN xc.key_ordinal IS NOT NULL THEN All_PKs.PrimaryKey 
      ELSE NULL 
     END AS PK 
     ,CASE 
      WHEN ic.column_id IS NULL THEN '' 
      ELSE ' identity('+ISNULL(CONVERT(varchar(10),ic.seed_value),'')+','+ISNULL(CONVERT(varchar(10),ic.increment_value),'')+')='+ISNULL(CONVERT(varchar(10),ic.last_value),'null') 
     END 
     +CASE 
      WHEN sc.column_id IS NULL THEN '' 
      ELSE ' computed('+ISNULL(sc.definition,'')+')' 
     END 
     +CASE 
      WHEN cc.object_id IS NULL THEN '' 
      ELSE ' check('+ISNULL(cc.definition,'')+')' 
     END 
      AS MiscInfo 
    FROM sys.objects       o 
     INNER JOIN sys.schemas    sh on o.schema_id=sh.schema_id 
     INNER JOIN sys.columns     s ON o.object_id=s.object_id 
     INNER JOIN sys.types     t ON s.system_type_id=t.system_type_id and t.is_user_defined=0 
     LEFT OUTER JOIN sys.identity_columns ic ON s.object_id=ic.object_id AND s.column_id=ic.column_id 
     LEFT OUTER JOIN sys.computed_columns sc ON s.object_id=sc.object_id AND s.column_id=sc.column_id 
     LEFT OUTER JOIN sys.check_constraints cc ON s.object_id=cc.parent_object_id AND s.column_id=cc.parent_column_id 
     LEFT OUTER JOIN sys.indexes   x ON o.object_id=x.object_id AND x.is_primary_key=1 
     LEFT OUTER JOIN sys.index_columns  xc ON o.object_id=xc.object_id AND x.index_id=xc.index_id AND s.column_id=xc.column_id 
     LEFT OUTER JOIN (SELECT --build the concatenated PK here 
          oo.object_id 
            ,STUFF(
              (
               SELECT 
                ', '+s.Name 
                FROM sys.objects       o 
                 LEFT OUTER JOIN sys.indexes   x ON o.object_id=x.object_id AND x.is_primary_key=1 
                 LEFT OUTER JOIN sys.index_columns  xc ON o.object_id=xc.object_id AND x.index_id=xc.index_id 
                 LEFT OUTER JOIN sys.columns   s ON o.object_id=s.object_id AND s.column_id=xc.column_id 
               WHERE oo.object_id=o.object_id AND xc.column_id IS NOT NULL 
               ORDER BY o.object_ID,xc.key_ordinal 
               FOR XML PATH('') 
              ) 
              ,1,2, '' 
             ) AS PrimaryKey 
           FROM sys.objects oo 
           -- 
           --REMOVE comments to filter the query 
           --WHERE [email protected] 
           -- 
         )All_PKs ON o.object_id=All_PKs.object_id 
    -- 
    --REMOVE comments to filter the query 
    --WHERE sh.name [email protected] 
    -- AND [email protected] 
    -- AND [email protected] 
    -- 
    ORDER BY sh.name+'.'+o.name,s.column_id 

Puede eliminar el comentario de la WHERE para filtrar por el esquema/tabla/columna.

También puedes, simplemente crear un trigger para que le avise de los cambios:

create this log table first: 

CREATE TABLE YourLogTable (EventID int not null identity(1,1), EventDateTime datetime null, EventDescription varchar(MAX) null) 

USE [TheDatabase] 
GO 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TRIGGER [YourDatabaseTrigger] 
ON DATABASE 
FOR DDL_DATABASE_LEVEL_EVENTS --DDL_TABLE_EVENTS --DDL_EVENTS 
AS 

DECLARE @EventData  xml 
DECLARE @Message  varchar(1000) 
SET @EventData=EVENTDATA() 

INSERT INTO YourLogTable 
    (EventDateTime,EventDescription) 
    VALUES (GETDATE(),--SUSER_NAME() 
        --+'; '[email protected]('(/EVENT_INSTANCE/ObjectType)[1]', 'varchar(500)') 
        --+'; '[email protected]('(/EVENT_INSTANCE/ObjectName)[1]', 'varchar(500)') 
        --+'; '[email protected]('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(8000)') 
        CONVERT(varchar(max),@EventData) 
      ) 
RETURN 

GO 
SET ANSI_NULLS OFF 
GO 
SET QUOTED_IDENTIFIER OFF 
GO 
ENABLE TRIGGER [YourDatabaseTrigger] ON DATABASE 

que le permitirá ver todos los cambios realizados a la base de datos.

+0

Esto es realmente genial. No utilicé tu código como tal, pero me abrió muchas puertas, lo cual es mejor que simples modismos y scripts. – MetaHyperBolic

8

Echa un vistazo a Information_Schema views.

+0

wow!eso es una gran cantidad de votos para un enlace tan genérico, que ni siquiera tiene ningún código para hacer lo que el OP está buscando. –

Cuestiones relacionadas