我正在尝试动态创建代码以将列定义更改为字段的最大长度。
请注意,数据库的内容不会改变。
这是我到目前为止所拥有的,但我不能单独执行最大长度查询来获取数字。我哪里错了?
问候。
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)
答案 0 :(得分:0)
编辑我的第一个版本不够精确,这是我测试过的新版本:
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)
答案 1 :(得分: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
答案 2 :(得分:-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在没有低效存储数据方面要好得多,但改变列大小通常仍然是不好的做法。