动态 T-SQL - 将列定义更改为字段的最大长度

问题描述 投票:0回答:4

我正在尝试动态创建代码以将列定义更改为字段的最大长度。

注意数据库的内容不会改变。

这是我到目前为止所拥有的,但我无法单独执行最大长度查询来获取数字。我哪里错了?

问候。

DECLARE @SQL_STMT VARCHAR(MAX) = ''

SELECT @SQL_STMT = @SQL_STMT
    + '''ALTER TABLE '
    + TABLE_NAME
    + ' ALTER COLUMN '
    + COLUMN_NAME
    + ' '
    + DATA_TYPE
    + '('' SELECT MAX(LEN('
    + COLUMN_NAME
    + ')) FROM '
    + TABLE_NAME
    + ''') ''
    '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'varchar'

PRINT(@SQL_STMT)
sql-server dynamic-sql alter-column
4个回答
1
投票

编辑我的第一个版本不够完善,这是我测试过的新版本:

DECLARE @SQL_STMT VARCHAR(MAX) = 'DECLARE @query nvarchar(max);'

SELECT @SQL_STMT = @SQL_STMT
    + 'SET @query =''ALTER TABLE '
    + TABLE_NAME
    + ' ALTER COLUMN '
    + COLUMN_NAME
    + ' '
    + DATA_TYPE
    + '('' +CAST((SELECT MAX(DATALENGTH('
    + COLUMN_NAME
    + ')) FROM '
    + TABLE_NAME
    + ') as nvarchar(max))+'') ''
    exec(@query);'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'nvarchar'

PRINT(@SQL_STMT)

0
投票

我不喜欢这个想法,但这应该可以实现你想要的:

DECLARE @SQL_STMT VARCHAR(MAX) = ''

SELECT 
    IDENTITY(int,1,1) as ID, -- for later update   
     'ALTER TABLE '
    + c.TABLE_NAME
    + ' ALTER COLUMN '
    + c.COLUMN_NAME
    + ' '
    + c.DATA_TYPE
    + '('  P1

    , '  MAX(LEN('
    + c.COLUMN_NAME
    + ')'
    +') FROM '
    + c.TABLE_NAME P2

    , ') ' P3
into #tmp    
FROM INFORMATION_SCHEMA.Tables t 
JOIN INFORMATION_SCHEMA.Columns c 
on    c.TABLE_CATALOG= t.TABLE_CATALOG 
  and c.TABLE_SCHEMA=t.TABLE_SCHEMA
  and c.TABLE_NAME=t.TABLE_NAME
where TABLE_TYPE='BASE TABLE' -- only Tables not views
and DATA_TYPE = 'varchar'

Select @SQL_STMT=''  -- collect ID + Max info e.g. SELECT 1,   MAX(LEN(FirstName)) FROM user_info 
Select @SQL_STMT=@SQL_STMT + 'SELECT '+ CAST(ID as varchar(10)) + ', '+ P2 +CHAR(13) 
from #tmp

Declare @a table (ID Integer,Size Integer) -- table for ID and Len
--print @SQL_STMT

insert into @a Exec (@SQL_STMT)  -- fill table by executing block

                     -- define a minimum size if 0  
Update #tmp set P2 = Case When Size<1 then 1 else Size end  -- update p2
From @a a where a.ID = #tmp.ID

Select @SQL_STMT=''
Select @SQL_STMT=@SQL_STMT + P1 + P2 + P3 +CHAR(13) 
from #Tmp

print @SQL_STMT

Exec(@SQL_STMT)


Drop table #tmp

0
投票
enter `SET @current_date = CURDATE();

SET @end_date = DATE_ADD(@current_date, INTERVAL 2 YEAR);

设置@current_year = YEAR(@current_date); 设置@current_month = MONTH(@current_date);

设置@sql = '';

同时@current_date <= @end_date DO SET @table_name = CONCAT('log_', @current_year, '_', LPAD(@current_month, 2, '0'));

SET @sql = CONCAT(@sql, 'ALTER TABLE ', @table_name, ' MODIFY COLUMN message VARCHAR(512); ', CHAR(10));

-- Move to the next month
SET @current_date = LAST_DAY(@current_date) + INTERVAL 1 DAY;
SET @current_year = YEAR(@current_date);
SET @current_month = MONTH(@current_date);

结束;

-- 输出动态生成的SQL SELECT @sql ASdynamic_sql;` 这里


-1
投票

您不能使用

SELECT
语句或整型变量作为
ALTER TABLE
语句中列的大小。 一般来说,您不能混合使用 DDL(数据描述语言,例如
CREATE
ALTER
DROP
)和 DML(数据操作语言,例如
SELECT
INSERT
UPDATE
) )在同一个声明中。

这意味着您必须使用动态 SQL 才能完成任务。 您将无法使用动态 SQL 来构建可以保存和重用的静态 SQL。 您需要检索字段的最大长度并将其保存到变量中,然后构造

ALTER
语句,最后构造
EXEC ()
ALTER
语句。 最简单的方法可能是使用光标通过
INFORMATION_SCHEMA.COLUMNS
,但您也可以使用双动态 SQL。 也就是说,动态SQL本身生成动态SQL。 然而,这更难调试。

除此之外,我质疑你正在尝试做的事情的有效性。 简而言之,您永远不需要使用此代码。 数据库模式应该相对固定,因为更改它会对性能产生重大影响。 通过更改列的大小,您可以告诉数据库引擎它需要更改在磁盘上物理存储数据的方式,而这不是您应该轻松或定期执行的操作。 只需将值设置得足够大以满足用户需求,您就会走得更远。 现代 RDBMS 在不低效存储数据方面做得更好,但经常更改列大小仍然是不好的做法。

© www.soinside.com 2019 - 2024. All rights reserved.