主要目的是去掉毫秒:
sql
DECLARE @SchemaName NVARCHAR(128)
DECLARE @TableName NVARCHAR(256)
DECLARE @FullTable NVARCHAR(517)
DECLARE @SQL NVARCHAR(MAX)
DECLARE @ConstraintName NVARCHAR(300)
-- 游标:查找所有含 cjsj 列的用户表
DECLARE TableCursor CURSOR FOR
SELECT
s.name,
t.name
FROM sys.tables t
JOIN sys.schemas s ON t.schema_id = s.schema_id
JOIN sys.columns c ON t.object_id = c.object_id
WHERE c.name = 'cjsj'
AND t.is_ms_shipped = 0
ORDER BY s.name, t.name
OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @FullTable = QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TableName)
PRINT 'Processing: ' + @FullTable
BEGIN TRY
-- === 合规性检查(兼容旧版)===
DECLARE @IsCompliant BIT = 0
SELECT
@IsCompliant = CASE
WHEN
TYPE_NAME(c.user_type_id) = 'datetime2'
AND c.scale = 0 -- 注意:datetime2 的小数位数存储在 scale(不是 precision!)
AND c.is_nullable = 0
AND dc.definition = '(getdate())'
THEN 1
WHEN
TYPE_NAME(c.user_type_id) = 'datetime'
AND c.is_nullable = 0
AND dc.definition = '(getdate())'
THEN 0 -- datetime 需要升级到 datetime2(0),不算合规
ELSE 0
END
FROM sys.columns c
LEFT JOIN sys.default_constraints dc
ON c.object_id = dc.parent_object_id
AND c.column_id = dc.parent_column_id
WHERE c.object_id = OBJECT_ID(@FullTable)
AND c.name = 'cjsj'
IF ISNULL(@IsCompliant, 0) = 1
BEGIN
PRINT ' -> Already compliant (datetime2(0) NOT NULL DEFAULT GETDATE()), skipping.'
FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName
CONTINUE
END
-- === 处理不合规表 ===
BEGIN TRANSACTION
-- 获取当前列信息
DECLARE @CurrentType NVARCHAR(128), @IsNullable BIT
SELECT
@CurrentType = TYPE_NAME(c.user_type_id),
@IsNullable = c.is_nullable
FROM sys.columns c
WHERE c.object_id = OBJECT_ID(@FullTable) AND c.name = 'cjsj'
-- 数据清洗(兼容旧版)
IF @CurrentType NOT IN ('datetime', 'datetime2')
BEGIN
PRINT ' -> Cleaning non-date values in cjsj (using ISDATE)...'
-- 使用 ISDATE 安全转换
SET @SQL = '
UPDATE ' + @FullTable + '
SET cjsj = CASE
WHEN cjsj IS NULL THEN GETDATE()
WHEN ISDATE(cjsj) = 1 THEN CONVERT(datetime, cjsj)
ELSE GETDATE()
END
WHERE cjsj IS NULL OR ISDATE(cjsj) = 0'
EXEC sp_executesql @SQL
END
ELSE
BEGIN
-- 仅填充 NULL
SET @SQL = 'UPDATE ' + @FullTable + ' SET cjsj = GETDATE() WHERE cjsj IS NULL'
EXEC sp_executesql @SQL
PRINT ' -> Updated NULLs to GETDATE()'
END
-- 删除依赖对象(默认约束、CHECK、索引)
DECLARE @DropDependentsSQL NVARCHAR(MAX) = ''
-- 默认约束
SELECT @DropDependentsSQL += 'ALTER TABLE ' + @FullTable + ' DROP CONSTRAINT ' + QUOTENAME(dc.name) + ';'
FROM sys.default_constraints dc
JOIN sys.columns c ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id
WHERE dc.parent_object_id = OBJECT_ID(@FullTable) AND c.name = 'cjsj'
-- CHECK 约束
SELECT @DropDependentsSQL += 'ALTER TABLE ' + @FullTable + ' DROP CONSTRAINT ' + QUOTENAME(cc.name) + ';'
FROM sys.check_constraints cc
JOIN sys.columns c ON cc.parent_object_id = c.object_id AND cc.parent_column_id = c.column_id
WHERE cc.parent_object_id = OBJECT_ID(@FullTable) AND c.name = 'cjsj'
-- 非主键索引
DECLARE @IndexName NVARCHAR(128)
DECLARE IndexCursor CURSOR FOR
SELECT i.name
FROM sys.indexes i
JOIN sys.index_columns ic ON i.object_id = ic.object_id AND i.index_id = ic.index_id
JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
WHERE c.object_id = OBJECT_ID(@FullTable)
AND c.name = 'cjsj'
AND i.is_primary_key = 0
AND i.is_unique_constraint = 0
OPEN IndexCursor
FETCH NEXT FROM IndexCursor INTO @IndexName
WHILE @@FETCH_STATUS = 0
BEGIN
SET @DropDependentsSQL += 'DROP INDEX ' + QUOTENAME(@IndexName) + ' ON ' + @FullTable + ';'
FETCH NEXT FROM IndexCursor INTO @IndexName
END
CLOSE IndexCursor
DEALLOCATE IndexCursor
IF LEN(@DropDependentsSQL) > 0
BEGIN
EXEC sp_executesql @DropDependentsSQL
PRINT ' -> Dropped dependent objects'
END
-- 修改列为 datetime2(0) NOT NULL
SET @SQL = 'ALTER TABLE ' + @FullTable + ' ALTER COLUMN cjsj datetime2(0) NOT NULL'
EXEC sp_executesql @SQL
PRINT ' -> Altered column to datetime2(0) NOT NULL'
-- 添加默认约束
SET @ConstraintName = 'DF_' + @SchemaName + '_' + @TableName + '_cjsj'
IF LEN(@ConstraintName) > 128
SET @ConstraintName = LEFT(@ConstraintName, 120) + '_' + CAST(ABS(CHECKSUM(NEWID())) % 1000 AS VARCHAR(3))
SET @SQL = '
IF NOT EXISTS (
SELECT 1 FROM sys.default_constraints dc
JOIN sys.columns c ON dc.parent_object_id = c.object_id AND dc.parent_column_id = c.column_id
WHERE dc.parent_object_id = OBJECT_ID(''' + REPLACE(@FullTable, '''', '''''') + ''')
AND c.name = ''cjsj''
)
ALTER TABLE ' + @FullTable + ' ADD CONSTRAINT ' + QUOTENAME(@ConstraintName) + ' DEFAULT GETDATE() FOR cjsj'
EXEC sp_executesql @SQL
PRINT ' -> Added default constraint: ' + @ConstraintName
COMMIT TRANSACTION
PRINT ' -> SUCCESS'
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
PRINT 'ERROR in ' + @FullTable + ': ' + ERROR_MESSAGE()
END CATCH
FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName
END
CLOSE TableCursor
DEALLOCATE TableCursor