如何查询SQL Server以获取SQL Server 2005表列的创建日期?
我尝试使用sp_columns [tablename]
来获取该信息,但创建日期未包含在此存储过程中。
如何做到这一点?
答案 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;
</CommandText>
</TSQLCommand>
</EVENT_INSTANCE>
如果捕获每列详细信息(即NULL / NOT NULL,数据类型等)而不仅仅是名称,那将是很好的,但如果需要,可以从CommandText
中解析出来。元件。
答案 2 :(得分:1)
我认为没有办法获得单个列本身的修改或创建日期。 this和this中给出的查询将返回与包含列而非列的表相关的日期。因为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
我建立了一个过程,该过程通过电子邮件将结果发送给我,然后我知道源表的模式已更改,我需要在目标中对其进行更改。
然后您可以对此进行扩展并找到不同的列名,但是我的用例不需要这样做。