3

Microsoft SQL Server 2008 R2 で、null 許容列を非 null に変更したいと考えています。明らかに、データ型を次のように言い換えることでこれを行うことができます。

alter table t alter column c int not null

たとえば、列 tc が int データ型の場合。しかし、既存のデータ型を言い換えずに、一般的にはどうでしょうか? 私はそれに相当するものを探しています

alter table t alter column c not null

既存のデータ型は保持され、null 可能性のみがオフになります。

バックグラウンド

データベースの監査を行ったところ、列が null 許容として指定されているにもかかわらず、実際には null 値が発生しないという多くのケースが見つかりました。これらの列で null 値を禁止するようにスキーマを強化したいと思います。データ型が間違っている可能性があるため、それぞれの列を変更するために DDL を手動で書き込むと、エラーが発生しやすくなります。各列の既存のデータ型を出力するスキーマ ダンパー プログラムを使用してコードを自動的に生成することもできますが、ダンパー プログラムが最新のデータ型を認識せず、別のものを出力する場合 (例として、 datetime2 を認識せず、代わりに datetime を書き出します)。

SQL サーバーは、列の型が何であるかを既に認識しているため、それを保持して null 可能性をオフにするように指示する方法が確実にあります。

既存のデータ型を見つけて DDL に入れる以外にそれを行う方法が本当にない場合は、適切なツールを使用することをお勧めできますか? Sybase時代のdbschema.plについては知っていますが、スキーマビューから必要なステートメントを出力する、より現代的なもの、またはSQLのよく知られたフラグメントがあるかもしれません。

4

2 に答える 2

1

2 つのアプローチ:

1)この回答を拡張して、max_length、precision、scale、および collat​​ion_name の考慮事項を含めます。複数のスキーマがある場合は、それにも対応する必要があります。

SELECT
  'ALTER TABLE '
    +QUOTENAME(aud.[table_name])
    +' ALTER COLUMN '
    +QUOTENAME(aud.[column_name])
    +TYPE_NAME([system_type_id])
    +' NOT NULL;'
FROM MyColumnAuditList aud
INNER JOIN sys.columns col ON (
  col.[object_id] = OBJECT_ID(aud.[table_name]) AND
  col.[name] = aud.[column_name]
)

2) SSMS で、データベースを右クリックし、[スクリプト データベース] を選択します。任意のテキスト解析ツールを使用して、結果から列定義を抽出します。

于 2013-12-09T15:42:57.403 に答える
0

アノンが提案した「2つのアプローチ」の回答は役に立ちます。ウェブサイトのコメント ボックスには十分なテキストを入力できないため、最終的な回答をここに投稿します。

リンクされた回答には、データベースにないユーザーデータ型の特別な規定があるため、代わりに組み込みを使用していますtype_name。このクエリは、各列の型をリバース エンジニアリングしようとします。

select t.name,
       c.name,
       case
         when type_name(c.system_type_id) in (
             'int', 'real', 'float', 'date', 'time', 'datetime', 'datetime2',
             'tinyint', 'smallint', 'smalldatetime', 'bit', 'bigint', 'timestamp',
             'image'
           ) then type_name(c.system_type_id)
         else type_name(c.system_type_id) + '('
           + case
               when precision = 0 then convert(varchar(10), c.max_length)
               else convert(varchar(10), precision) + ', ' + convert(varchar(10), scale)
             end
           + ')'
         end as ty
from sys.tables t
join sys.columns c
  on t.object_id = c.object_id
where c.is_nullable = 1
and   c.is_computed = 0
and   t.schema_id = 1
order by t.name,
         c.name

次に、このクエリから各行を取得し、「alter table」を実行する前に null が存在しないことを確認できます。私は次のようなことをしています:

select case when
  exists (select 0 from TABLE)
  and not exists (select 0 from TABLE tablesample (1000 rows) where COLUMN is null)
then 1 else 0 end

各 TABLE に対して、最初のクエリによって返される COLUMN。2 番目のクエリが 1 を返す場合は、おそらく「テーブルの変更」を変更できます。定期的にチェックを実行する予定なので、上記の tablesample を使用してデータベースに負荷がかかりすぎるのを防ぎます。sp_spaceused によって返されるテーブルのサイズが 100 キロバイト未満の場合は、tablesample 句を省略します。

または、勇気がある場合は、すべての「alter table」ステートメントを実行して、列に null が含まれている場合はそれらを失敗させることができます。

奇妙なことに、Management Studio でデータベースを右クリックして「データベースを次のようにスクリプト化」する権限がありませんが、個々のオブジェクトに対しては実行できます。

于 2013-12-11T10:24:31.600 に答える