SQL Server查询以选择特定类型的所有列,并显示其最大值

时间:2016-07-15 05:34:10

标签: sql-server sql-server-2012 dynamic-sql sql-function

我正在使用SQL Server 2012。

我的查询的第一部分已在此thread中得到解答。但我还想要第二列,它将在相应的表中显示该列的相应最大值。

我尝试过这种方法:使用一个以表名和列名作为参数的函数,并返回最大值。但是从函数中使用动态SQL是违法的。而且,我似乎无法从SELECT查询中调用函数。

我也尝试过使用存储过程,但我无法弄清楚如何调用它并使用它。请建议其他方法来实现这一目标。

我是SQL Server新手。

由于

3 个答案:

答案 0 :(得分:2)

我认为最简单的解决方案是存储过程。据我所知:

  • 动态SQL不能放在函数中
  • 动态SQL不能放在OPENROWSET

另外,如果你写这样的程序:

  • 注意包含空格,qoutes(可能的SQL注入)的名称
  • 非索引列上的MAX(列)需要完全扫描(可能非常慢)
  • 可以复制表名和列名(放置在不同的模式中)

Id重复项和性能不是问题,请看下面的代码段:

CREATE PROC FindMaxColumnValues
    @type sysname  = '%',
    @table sysname = '%'
AS
DECLARE @result TABLE (TableName sysname, ColumnName sysname, MaxValue NVARCHAR(MAX))

DECLARE @tab sysname
DECLARE @col sysname
DECLARE cur CURSOR FOR
  SELECT TABLE_NAME TableName, COLUMN_NAME [Column Name]
  FROM INFORMATION_SCHEMA.COLUMNS
  WHERE DATA_TYPE LIKE @type and TABLE_NAME LIKE @table

OPEN cur

FETCH NEXT FROM cur INTO @tab, @col
WHILE @@FETCH_STATUS = 0
BEGIN
    DECLARE @sql nvarchar(MAX) = 'SELECT '+QUOTENAME(@tab,'''')+' [TableName], '+QUOTENAME(@col, '''')+' [ColumnName], MAX('+QUOTENAME(@col)+') FROM '+QUOTENAME(@tab)
    INSERT INTO @result EXEC(@sql)
    FETCH NEXT FROM cur INTO @tab, @col
END

CLOSE cur
DEALLOCATE cur

SELECT * FROM @result

<强>样品:

--MAX of INT's
EXEC FindMaxColumnValues 'INT'
--MAX of INT's in tables matching 'TestTab%'
EXEC FindMaxColumnValues 'INT', 'TestTab%'
--MAX of ALL columns
EXEC FindMaxColumnValues

<强>结果:

TableName   ColumnName   MaxValue
IdNameTest  ID           2
TestTable   ID           5
TestTable   Number       3

TableName   ColumnName   MaxValue
TestTable   ID           5
TestTable   Number       3

TableName       ColumnName   MaxValue
UpdateHistory   UpdateTime   2016-07-14 12:21:37.00
IdNameTest      ID           2
IdNameTest      Name         T2
TestTable       ID           5
TestTable       Name         F
TestTable       Number       3

答案 1 :(得分:0)

您可以使用以下SP并根据您的需要进行增强,

CRETE PROCEDURE Getmaxtablecolval
AS
  BEGIN
      CREATE TABLE #t
        (
           tablename  VARCHAR(50),
           columnname VARCHAR(50),
           id         INT,
           counts     INT
        )

      INSERT INTO #t
      SELECT table_name  [Table Name],
             column_name [Column Name],
             NULL,
             NULL
      FROM   information_schema.columns
      WHERE  data_type = 'INT'

      BEGIN TRAN

      DECLARE @id INT

      SET @id = 0

      UPDATE #t
      SET    @id = id = @id + 1

      COMMIT TRAN

      DECLARE @RowCount INT

      SET @RowCount = (SELECT Count(0)
                       FROM   #t)

      DECLARE @I INT

      SET @I = 1

      DECLARE @Counter INT
      DECLARE @TName VARCHAR(50)
      DECLARE @CName VARCHAR(50)
      DECLARE @DynamicSQL AS VARCHAR(500)

      WHILE ( @I <= @RowCount )
        BEGIN
            SELECT @TName = tablename
            FROM   #t
            WHERE  id = @I

            SELECT @CName = columnname
            FROM   #t
            WHERE  id = @I

            SET @DynamicSQL = 'Update #T Set Counts = '
                              + '(Select ISNull(Max(' + @CName + '), 0) From '
                              + @TName + ') Where Id = '
                              + CONVERT(VARCHAR(10), @I)

            --PRINT @DynamicSQL
            EXEC (@DynamicSQL)

            SET @I = @I + 1
        END

      SELECT *
      FROM   #t
  END

go

Getmaxtablecolval  

答案 2 :(得分:0)

您可以创建一个程序:

CREATE PROCEDURE GET_COLUMNS_WITH_MAX_VALUE

    @COLUMN_TYPE NVARCHAR(50)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- DUMMY VARIABLE TO COPY STRUCTURE TO TEMP
        DECLARE @DUMMY TABLE
    (
        TABLE_NAME NVARCHAR(50),
        COLUMN_NAME NVARCHAR(50),
        MAX_VALUE NVARCHAR(MAX)
    )

    -- CREATE TEMP TABLE FOR DYNAMIC SQL
    SELECT TOP 0 * INTO #TABLE FROM @DUMMY

    INSERT INTO #TABLE
    (TABLE_NAME,  COLUMN_NAME)
    SELECT TABLE_NAME, COLUMN_NAME
    FROM information_schema.columns where data_type = @COLUMN_TYPE

    DECLARE @TABLE_NAME VARCHAR(50) -- database name  
    DECLARE @COLUMN_NAME VARCHAR(256) -- path for backup files  

    DECLARE db_cursor CURSOR FOR  
    SELECT TABLE_NAME, COLUMN_NAME 
    FROM #TABLE

    OPEN db_cursor   
    FETCH NEXT FROM db_cursor INTO @TABLE_NAME, @COLUMN_NAME 

    WHILE @@FETCH_STATUS = 0   
    BEGIN   

    DECLARE @SQL NVARCHAR(MAX) =  'UPDATE #TABLE SET MAX_VALUE = (SELECT MAX([' + @COLUMN_NAME + ']) FROM [' + @TABLE_NAME + ']) '
                                 + 'WHERE [COLUMN_NAME] = ''' + @COLUMN_NAME + ''' AND TABLE_NAME = ''' + @TABLE_NAME  + '''';
    PRINT @SQL
    EXEC (@SQL)

    FETCH NEXT FROM db_cursor INTO @TABLE_NAME, @COLUMN_NAME 

    END   

    CLOSE db_cursor   
    DEALLOCATE db_cursor


    SELECT * FROM #TABLE

    DROP TABLE #TABLE

END
GO

<强>用法:

EXEC GET_COLUMNS_WITH_MAX_VALUE 'INT'

<强>结果:

TABLE1      ID      50
TABLE2      ID      100
TABLE3      CarID       20  
TABLE4      StudentID   30