1

列定義をフィールドの最大長に変更するコードを動的に作成しようとしています。

データベースの内容は変更されないことに注意してください。

ここに私がこれまでに持っているものがありますが、最大長のクエリを個別に実行して数値を取得することはできません。どこが間違っていますか?

よろしく。

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)
4

3 に答える 3

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)
于 2014-09-26T15:18:55.130 に答える
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
于 2014-09-26T15:44:46.390 に答える
-1

SELECTステートメント内の列のサイズとして、ステートメントまたは整数変数を使用することはできませんALTER TABLE。原則として、DDL (データ記述言語、CREATEALTERなどDROP) と DML (データ操作言語 、SELECTINSERTなどUPDATE) を同じステートメントに混在させることはできません。

これが意味することは、タスクを達成するためだけに動的 SQL を使用する必要があるということです。動的 SQL を使用して、保存して再利用できる静的 SQL を作成することはできません。フィールドの最大長を取得して変数に保存してから、ALTERステートメントを作成し、最後EXEC ()ALTERステートメントを作成する必要があります。これを行う最も簡単な方法は、おそらく を介してカーソルをINFORMATION_SCHEMA.COLUMNS使用することですが、二重に動的な SQL を使用することもできます。つまり、それ自体が動的 SQL を生成する動的 SQL です。ただし、これをデバッグするのははるかに困難です。

それを超えて、私はあなたがやろうとしていることの妥当性に疑問を投げかけています. 簡単に言えば、このコードを使用する必要はありません。データベース スキーマは、変更するとパフォーマンスに大きな影響を与えるため、比較的固定する必要があります。列のサイズを変更することで、データベース エンジンに対して、データをディスクに物理的に格納する方法を変更する必要があることを伝えることになります。これは、簡単に、または定期的に行うべきことではありません。ユーザーのニーズに対応するのに十分な大きさの値を設定するだけで、さらに先に進むことができます。最新の RDBMS は、データを非効率的に格納しないという点ではるかに優れていますが、多くの場合、列のサイズを変更することは依然として適切ではありません。

于 2014-09-26T15:22:01.590 に答える