2011年3月29日

Microsoft SQL Serverに関する些細な4つのTips

===========================================================
マザー・テレサの名言から考える「今、自分にできること。」 : earth in us.
===========================================================


自分の旧ブログからの転載です。


1. MS SQL Serverの@@IDENTITYで正しい値が取得出来ない時は。。。

SQLサーバーで@@IDENTITYを使うと、Insert直後にトリガーが走ってさらにその中で別のInsert文が実行される場合に意図した値が取得出来ないという問題に遭遇しました。
そこで調べて見た所、SCOPE_IDENTITY() という関数があるのを遅ればせながら今日知りました。^^;
これだとトリガーに関係なく自分の直前のInsert文の結果としての最新のIdentity値が取得出来るそうです。

SCOPE_IDENTITY (Transact-SQL)
http://msdn.microsoft.com/en-us/library/ms190315.aspx


Alternatives to @@IDENTITY in SQL Server 2000
http://www.sqlteam.com/article/alternatives-to-identity-in-sql-server-2000


Identity Crisis
http://msdn.microsoft.com/en-us/library/aa224821%28SQL.80%29.aspx


Getting the Wrong Identity in Microsoft SQL Server identity Columns?
http://www.databasejournal.com/features/mssql/article.php/10894_3307541_2/Getting-the-Wrong-Identity-in-Microsoft-SQL-Server-identity-Columns.htm


結論:

これからは@@IDENTITYではなく SCOPE_IDENTITY() を使おう!


注)もちろん場合によっては @@IDENTITYの方が望ましい場合もあるかも知れませんので、何でもかんでもという訳ではありません。。。



2. SQLServerのDB内の全テーブルのデータ容量を表示する

下の2つのサイトの情報を参考にして、全テーブルのデータ容量を表示するSQLを作ってみました。
レコード件数だけでなく、データ領域とインデックス領域の使用量も確認出来るので便利かなと。

[SQL]SQLServerのDB内に存際する全テーブルの件数取得(T-SQL)
http://genz0.blogspot.com/2009/04/sqlsqlserverdbt-sql.html


【SQL Server】テーブルの使用量を確認する
http://blog.livedoor.jp/akf0/archives/51427351.html



上記2つの作者様、情報ありがとうござました!

以下、SQLです。

SET NOCOUNT ON

--テーブル変数(結果格納用)
DECLARE @TEMP_TABLE table(
row_id int IDENTITY(1,1) NOT NULL
,T_NAME varchar(128) NULL
,T_CNT bigint
,T_DATA bigint -- KBytes
,T_INDEX bigint -- KBytes
PRIMARY KEY (row_id)
)

DECLARE @NAME nvarchar(128), @SQL nvarchar(256)
DECLARE @CNT bigint, @DATA bigint, @INDEX bigint
declare @row_id int


--カーソルの宣言
DECLARE cs CURSOR FOR
SELECT NAME FROM sysobjects where type='U' ORDER BY NAME

--カーソルのオープン
OPEN cs
FETCH NEXT FROM cs
INTO @NAME
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL = N'EXEC sp_MStablespace [' + @NAME + ']'

INSERT INTO @TEMP_TABLE (T_CNT, T_DATA, T_INDEX)
EXECUTE sp_executesql @SQL

SET @row_id = @@IDENTITY
update @TEMP_TABLE SET T_NAME = @NAME WHERE row_id = @row_id

FETCH NEXT FROM cs
INTO @NAME
END

CLOSE cs
DEALLOCATE cs

--実行結果を表示する
SELECT T_NAME, T_CNT, T_DATA, T_INDEX, (T_DATA+T_INDEX) / 1024 AS TOTAL_MB
FROM @TEMP_TABLE ORDER BY (T_DATA+T_INDEX) / 1024 DESC
SET NOCOUNT OFF



3. MS SQL Serverからメールを送信する

EXEC master.dbo.xp_sendmail
@recipients = @mailto,
@query = @sql,
@subject = @sub,
@message = @msg,
@attach_results = 'True',
@width = 2000

注)使用するにはSQLサーバー側でメールサーバーの設定が必要。



4. ストアド内のSQLのエラー

他社が開発したあるシステムで、データ取り込み処理の途中でSQLエラーが発生してしまいました。「文字列が長すぎるからフィールドに入らないよー」っていうワーニングでした。

諸般の事情で仕方なく無視して続行させたいのですが、デバッグしようにもものすごく長いストアドなので、なかなか厄介なんです。

結局、ストアドの最初に「SET ANSI_WARNINGS OFF」っていう1行を入れて逃げました。^^;
もちろん本当は良くないのですが、最悪の場合こう言う逃げ方もあると言う事で。




===========================================================
マザー・テレサの名言から考える「今、自分にできること。」 : earth in us.
===========================================================







.