我有一堆表,有些表有日期时间列,有些则没有。对于包含日期时间列的所有表,我想找到最大值并输出它。到目前为止我所做的是:
DECLARE @AllTables TABLE(TableNumber INT, TableName NVARCHAR(255))
DECLARE @AllColumns TABLE(ColumnNumber INT, ColumnName NVARCHAR(255), TableName NVARCHAR(255))
DECLARE @OrderedColumns TABLE(EntryNumber INT, ColumnName NVARCHAR(255), TableName NVARCHAR(255))
DECLARE @I INT = 1
DECLARE @J INT = 1
DECLARE @TableCount INT
DECLARE @ColumnCount INT
DECLARE @CurrentTableName NVARCHAR(255)
DECLARE @CurrentColumnName NVARCHAR(255)
DECLARE @HighestDate DATETIME
DECLARE @TotalHighestDate DATETIME = '1970-01-01'
DECLARE @SQL NVARCHAR(MAX)
DECLARE @CurrentDate DATETIME = CURRENT_TIMESTAMP
--List all relevant tables
INSERT INTO @AllTables
SELECT ROW_NUMBER() OVER(ORDER BY TABLE_NAME) AS Row, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE 'XYZ%' AND TABLE_TYPE = 'BASE TABLE'
SET @TableCount = (SELECT COUNT(*) FROM @AllTables)
--Loop through all the tables and get the column names for datetime columns
WHILE @I <= @TableCount
BEGIN
SET @CurrentTableName = (SELECT TableName FROM @AllTables WHERE TableNumber = @I)
INSERT INTO @AllColumns
SELECT ROW_NUMBER() OVER(ORDER BY COLUMN_NAME) AS Row, COLUMN_NAME, TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE LIKE 'datetime%' AND TABLE_NAME = @CurrentTableName
SET @I = @I + 1
END
--Order the columns so they can be looped through
INSERT INTO @OrderedColumns
SELECT ROW_NUMBER() OVER(ORDER BY TableName,ColumnName) AS Row, ColumnName, TableName FROM @AllColumns
SET @ColumnCount = (SELECT COUNT(*) FROM @OrderedColumns)
--Get the highest date for each column and update the total highest date if the date we found is higher than the current record holder
WHILE @J <= @ColumnCount
BEGIN
SET @CurrentColumnName = (SELECT ColumnName FROM @OrderedColumns WHERE EntryNumber = @J)
SET @CurrentTableName = (SELECT TableName FROM @OrderedColumns WHERE EntryNumber = @J)
SET @SQL = 'SELECT @HighestDateOUTPUT = MAX(' + @CurrentColumnName + ') FROM [dbo].[' + @CurrentTableName +']'
EXECUTE sp_executesql @SQL,N'@HighestDateOUTPUT DATETIME OUTPUT',@HighestDateOUTPUT = @HighestDate OUTPUT
--Ignore any results that are in the future, that data is incorrect and should be fixed at the source, not here
IF (@HighestDate > @TotalHighestDate AND @TotalHighestDate < @CurrentDate AND @HighestDate < @CurrentDate)
BEGIN
SET @TotalHighestDate = @HighestDate
END
SET @J = @J + 1
END
PRINT @TotalHighestDate
这运行良好并正确输出所有列中的最高日期。问题是,当我将其作为存储过程运行时,过程是
CREATE OR ALTER PROCEDURE [dbo].[MyHighestDateProcedure]
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
SET NOCOUNT ON;
...
--The above code block
...
END
失败并出现错误
Msg 156, Level 15, State 1, Line 3
Incorrect syntax near the keyword 'AS'.
大约四分之一的人会尝试它正确运行,但这是奇怪的部分。我的同事说“在存储过程中使用动态 sql 是一场噩梦,你在玩火,sql 缓存执行计划这可能是这些东西的问题”所以如果我的方法可以通过避免动态 SQL 来改进那么我是所有的耳朵。
编辑:澄清一下,我想从所有不同的日期时间列中找到单个最高日期,而不是每列的最高日期,结果应该是一个日期时间输出。
很可能是因为列名包含空格或特殊字符。您可以在列名上使用
quotename()
来处理这种情况
将动态查询更改为
SET @SQL = 'SELECT @HighestDateOUTPUT = MAX(' + quotename(@CurrentColumnName) + ') FROM [dbo].[' + @CurrentTableName +']'.