主SQL查询 - 查找1表中包含大于包含最大值的所有列

时间:2011-09-20 01:11:07

标签: sql minimum required

好吧,例如我有varchar 200列,但它有最多25个varchar值。因此,此查询应返回此列。此查询应该遍历所选表中的所有列,并返回所有这些结果。因此,我们可以检查列结构并采取适当的措施。

我的意思是:“找到所有列定义为宽于其中最大实际数据值的列”

1 个答案:

答案 0 :(得分:1)

你没有说明我所采用的RDBMS是一般的方法。 INFORMATION_SCHEMA表通常由大型RDBMS安装支持(它是一个标准,适用于所有值得的)。如果没有,请调整它以适应可用的元数据以及语法奇怪。方法本身就是合理的。

SET NOCOUNT ON;

-- Create a local table for processing
DECLARE
    @RESIZING TABLE
(
    resizing_id int identity(1,1) NOT NULL PRIMARY KEY
,   schemaname sysname
,   tablename sysname
,   columnname sysname
,   datatype sysname
,   max_length int
,   current_length int
);

-- Use the ANSI standard view for system meta data
-- to populate tables. Only focusing on varchar fields
-- as they are the only ones that will provide useful
-- sizing information. 
-- To make it work with chars, update the query individual
-- queries to perform a trim operation before calling len
-- and obviously update the data_type to include char
INSERT INTO
    @RESIZING 
SELECT
    ISC.TABLE_SCHEMA
,   ISC.TABLE_NAME
,   ISC.COLUMN_NAME
,   ISC.DATA_TYPE
,   ISC.CHARACTER_MAXIMUM_LENGTH
,   NULL AS current_length
FROM
    INFORMATION_SCHEMA.COLUMNS ISC
WHERE
    ISC.DATA_TYPE = 'varchar';


-- Create a cursor
-- Kill a kitten
DECLARE
    Csr CURSOR 
FOR
SELECT
    -- build out a query like
    -- SELECT @current_len = MAX(LEN(X.[COLUMN_NAME])) FROM [dbo].[TABLE] X WITH(NOLOCK) 
    'SELECT @current_len = MAX(LEN(X.[' 
    + R.columnname 
    + '])) FROM [' 
    + R.schemaname 
    + '].[' 
    + R.tablename 
    + '] X WITH(NOLOCK) ' AS query
,   R.current_length
FROM
    @RESIZING R
FOR UPDATE OF current_length;

-- 2 local variables, one for the dynamic query
-- one to hold the results of said query
DECLARE
    @query nvarchar(max)
,   @current_length int;

OPEN
    Csr;

FETCH NEXT 
FROM Csr
INTO @query, @current_length;

WHILE @@FETCH_STATUS = 0
BEGIN
    -- try before you buy
    PRINT @query;

    -- Run the query, assigning length to @current_length variable
    EXECUTE sp_executesql @query, N'@current_len int OUTPUT', @current_len = @current_length OUTPUT;

    -- Push results int our temporary table
    UPDATE
        R
    SET
        current_length = @current_length
    FROM
        @RESIZING R
    WHERE
        CURRENT OF Csr;

    FETCH NEXT 
    FROM Csr
    INTO @query, @current_length;
END

CLOSE Csr;
DEALLOCATE Csr;


-- Result the resultset for all the
-- tables with longer lengths than used
-- (NULLS included)
SELECT
    *
FROM
    @RESIZING R
WHERE
    R.max_length > isnull(@current_length, 0)

结果(SQL Server 2008 R2)

resizing_id | schemaname | tablename    | columnname | datatype | max_length | current_length
1           | dbo        | DupesOk      | name       | varchar  | 50         | 12
2           | dbo        | SALES_HEADER | CCCode     | varchar  | 15         | 15
3           | lick       | ABC          | value      | varchar  | 50         | 8