查找表的列的创建日期/时间

时间:2009-09-15 06:39:33

标签: sql sql-server sql-server-2005 tsql

如何查询SQL Server以获取SQL Server 2005表列的创建日期?

我尝试使用sp_columns [tablename]来获取该信息,但创建日期未包含在此存储过程中。

如何做到这一点?

8 个答案:

答案 0 :(得分:8)

这个名为sys.Columns的系统表可以从中获取列信息。 如果您想查看特定表的列,可以按如下方式执行:

SELECT col.* from sys.objects obj 
inner join sys.columns col 
on obj.object_Id=col.object_Id 
and obj.Name=@tableName

或者您可以获得这样的表格信息:

SELECT * FROM sys.objects WHERE Name=@tableName

但是我找不到关于列创建日期的任何信息。

更新: This 可能有帮助。

答案 1 :(得分:7)

SQL Server无法跟踪表的特定更改。如果您需要或需要此级别的详细信息,则需要创建可以捕获某些特定事件甚至事件类的DDL触发器(在SQL Server 2005中引入),并将这些更改记录到您创建的历史记录表中。

DDL触发器是“后”触发器;没有“代替”选项。但是,如果您想禁止某项操作,则只需发出ROLLBACK即可取消所发生的操作。

DDL Triggers的MSDN页面有很多关于如何捕获特定事件(即ALTER TABLE)和使用返回XML的EVENTDATA函数以获取什么事件触发了触发器的细节,包括执行的确切SQL查询。事实上,Use the EVENTDATA Function的MSDN页面甚至有一个简单的例子,可以创建一个DDL触发器来捕获ALTER TABLE语句(在“ ALTER TABLE和ALTER DATABASE事件“部分”并创建一个DDL触发器以将事件捕获到日志表中(在“示例”部分中)。由于所有ALTER TABLE命令都将触发此触发器,您需要解析哪个那些是特定于你正在寻找的。并且,现在你可能知道这是一个选项,需要捕获的不仅仅是添加列(即删除列,更改数据类型和/或可空性等)。

应该注意,您可以为ON ALL SERVER等数据库范围的事件创建DLL触发器ALTER_TABLE

如果要查看任何事件或事件类的XML结构,请转到:

http://schemas.microsoft.com/sqlserver/2006/11/eventdata/

并单击“当前版本:”链接。如果要查看特定事件或事件类,只需在触发器的“FOR”子句(包括下划线)中使用的事件名称上进行搜索(通常在浏览器中为Control-F)。以下是ALTER_TABLE事件的架构:

<xs:complexType name="EVENT_INSTANCE_ALTER_TABLE">
<xs:sequence>
<!--  Basic Envelope  -->
<xs:element name="EventType" type="SSWNAMEType"/>
<xs:element name="PostTime" type="xs:string"/>
<xs:element name="SPID" type="xs:int"/>
<!--  Server Scoped DDL  -->
<xs:element name="ServerName" type="PathType"/>
<xs:element name="LoginName" type="SSWNAMEType"/>
<!--  DB Scoped DDL  -->
<xs:element name="UserName" type="SSWNAMEType"/>
<!--  Main Body  -->
<xs:element name="DatabaseName" type="SSWNAMEType"/>
<xs:element name="SchemaName" type="SSWNAMEType"/>
<xs:element name="ObjectName" type="SSWNAMEType"/>
<xs:element name="ObjectType" type="SSWNAMEType"/>
<xs:element name="Parameters" type="EventTag_Parameters" minOccurs="0"/>
<xs:element name="AlterTableActionList" type="AlterTableActionListType" minOccurs="0"/>
<xs:element name="TSQLCommand" type="EventTag_TSQLCommand"/>
</xs:sequence>
</xs:complexType>

这是一个非常简单的测试,看看它是如何工作的以及产生的EventData XML的结果:

IF (EXISTS(
   SELECT *
   FROM   sys.server_triggers sst
   WHERE  sst.name = N'CaptureAlterTable'
   ))
BEGIN
  DROP TRIGGER CaptureAlterTable ON ALL SERVER;
END;
GO

CREATE TRIGGER CaptureAlterTable
ON ALL SERVER -- capture events for all databases
FOR ALTER_TABLE -- only capture ALTER TABLE events
AS
  PRINT CONVERT(NVARCHAR(MAX), EVENTDATA()); -- Display in "Messages" tab in SSMS
GO

首先,我们在tempdb中创建一个简单的实际表(不会为临时表捕获这些事件):

USE [tempdb];
CREATE TABLE dbo.MyAlterTest (Col2 INT NULL);

接下来我们添加一列。我们从另一个数据库执行此操作,以确保XML捕获对象所在的数据库而不是当前数据库。请注意单词alTeR Table tempDB.dbo.MyALTERTest ... DATEcreated的大小写以与XML中的内容进行比较。

USE [master];
alTeR Table tempDB.dbo.MyALTERTest ADD DATEcreated DATETIME NOT NULL;

您应该会在“消息”标签中看到以下内容(我添加的评论):

<EVENT_INSTANCE>
  <EventType>ALTER_TABLE</EventType>
  <PostTime>2014-12-15T10:53:04.523</PostTime>
  <SPID>55</SPID>
  <ServerName>_{server_name}_</ServerName>
  <LoginName>_{login_name}_</LoginName>
  <UserName>dbo</UserName>
  <DatabaseName>tempdb</DatabaseName> <!-- casing is based on database definition -->
  <SchemaName>dbo</SchemaName>
  <ObjectName>MyAlterTest</ObjectName> <!-- casing is based on object definition -->
  <ObjectType>TABLE</ObjectType>
  <AlterTableActionList>
    <Create>
      <Columns>
        <Name>DATEcreated</Name> <!-- casing is taken from executed query -->
      </Columns>
    </Create>
  </AlterTableActionList>
  <TSQLCommand>
    <SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE"/>
    <CommandText>alTeR Table tempDB.dbo.MyALTERTest ADD DATEcreated DATETIME NOT NULL;&#x0D;
</CommandText>
  </TSQLCommand>
</EVENT_INSTANCE>

如果捕获每列详细信息(即NULL / NOT NULL,数据类型等)而不仅仅是名称,那将是很好的,但如果需要,可以从CommandText中解析出来。元件。

答案 2 :(得分:1)

我认为没有办法获得单个列本身的修改或创建日期。 thisthis中给出的查询将返回与包含列而非列的表相关的日期。因为sys.columns表对表中的所有列具有相同的id。您可以通过运行此查询来验证这一点

select col.object_id, col.name, col.column_id
from sys.columns col
where col.object_id = 
(select o.object_id from sys.objects o where o.Name = @tableName)

答案 3 :(得分:1)

参加派对的时间晚了,但发现了对我有帮助的东西。如果您可以说该列是表格的最后一次更改,那么sys.tables(modify_date)是可行的。

答案 4 :(得分:1)

SELECT so.name,so.modify_date
FROM sys.objects as so
    INNER JOIN INFORMATION_SCHEMA.TABLES as ist
ON ist.TABLE_NAME=so.name where ist.TABLE_TYPE='BASE TABLE' AND
 TABLE_CATALOG='dbName' order by so.modify_date desc;

答案 5 :(得分:0)

SELECT obj.create_date 
from sys.objects obj 
inner join sys.columns col on obj.object_Id=col.object_Id 
WHERE col.name = @columnName
and obj.Name=@tableName

以前一个答案为基础,但仅给出列的创建日期

答案 6 :(得分:0)

除非您有可以浏览事务日志的内容,例如Log Explorer,否则我认为此信息不可用。这不是一个tsql的事情。

答案 7 :(得分:0)

我遇到一个问题,我不得不将表复制到另一台服务器,我想做这件事,但是sys表中没有任何内容显示添加或更改列的时间。由于我知道当前表具有正确的列,因此我在do循环中执行了以下操作:

declare @CurrentTableCount int = 0,
        @SchemaCheckTableCount = 0

  select top 1 * into TableNameSchemaCheck from OpenQuery
 (Database, 'select * from TableName where 1 = 2')

 select @CurrentTableCount = (select count(1) from sys.syscolumns c
                                inner join sys.sysobjects o on c.id = o.id
                                  where o.xtype = 'U'
                                    and o.name = 'TableName')

 select @SchemaCheckTableCount = (select count(1) from sys.syscolumns c
                                   inner join sys.sysobjects o on c.id = o.id
                                   where o.xtype = 'U'
                                     and o.name = 'TableNameSchemaCheck')

    if @CurrentTableCount <> @SchemaCheckTableCount
     begin

      insert into SchemaCheckLog
       values ('CompanyContext', getdate(), 'Schema for TableName table has changed.', 0)

       end

     drop table TableNameSchemaCheck

 end

我建立了一个过程,该过程通过电子邮件将结果发送给我,然后我知道源表的模式已更改,我需要在目标中对其进行更改。

然后您可以对此进行扩展并找到不同的列名,但是我的用例不需要这样做。