2011-09-20 64 views
0

好吧例如我有varchar 200列,但它具有最大值为25的varchar值。所以这个查询应该返回这个列。该查询应该贯穿选定表格中的所有列并返回所有这类结果。所以我们可以检查列结构并采取适当的行动。主SQL查询 - 查找1个表中的所有列的类型比包含最大值的类型更大

我的意思是:“找我被定义为比他们最大的实际数据值更宽的所有列”

+1

他的意思是“找到我,被定义为比他们最大的实际数据值更宽的所有列” – Bohemian

+0

感谢编辑的问题:d – MonsterMMORPG

+0

你做意识到你不需要花费更多的存储空间来存储varchar(8000)中的10个字符而不是varchar(10)?我完全支持正确的数据类型,请不要误解我的意思。 – billinkc

回答

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 
+0

这是否只显示字符列不int或小int等等? – MonsterMMORPG

+1

它目前只针对你的问题设置了varchar。 ;)处理整个数字类型的逻辑不会更难。十进制类型,那些会变得更丑陋 – billinkc

+0

你可以请修改显示数字:D谢谢。 – MonsterMMORPG