プログラ生活

プログラム初学者のためのポイントを書いていこうと思います。たまに脇道それた記事もありますが、息抜きだとおもって気長にお付き合いください。

【SQL Server(連載)】正規化(第3正規化) -36-

www.pon-x.jp

前回の続き

今回は、第3正規化についてのはなしです。

第3正規化

前回まで第2正規化まで行い、以下のテーブルが得られました。

TABLE: 売上 Primary Key:注文番号、商品ID

注文番号 注文年月日 商品ID 数量 顧客ID 顧客名 顧客TEL 顧客住所
1001 2020/12/20 K101 3 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K112 2 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K126 1 P501 岡氏 好男 0000-00-0000 東京都
1002 2020/12/21 Y516 2 P905 野菜 好子 1111-11-1111 埼玉県
1002 2020/12/21 Y842 3 P905 野菜 好子 1111-11-1111 埼玉県




TABLE: 商品 Primary Key:商品ID

商品ID 商品名 単価
K101 うまい棒 10
K112 がりがりくん 60
K126 チップスター 150
Y516 とまと 90
Y842 きゅうり 30

前回、関数従属性の説明をしましたね。
そのことから、商品テーブルにカラムを分離させてあげたということです。

第2正規化は主キーに対いて従属しているカラムを分離させましたが、主キー以外の項目についても従属関係があるカラムがあるとき、これを推移的関数従属といい、別テーブルに切り分ける必要があります。
これを第3正規化といい、第3正規化した結果を第3正規形といいます。

推移的関数従属

上述しましたが、推移的関数従属は主キー以外のカラムで従属関係にあるカラムをテーブル分離することですが、今回のケースは売上テーブルの、顧客IDに対する、顧客名と顧客TELと顧客住所がこれにあたります。
なぜなら、顧客IDはユニークなはずなので、顧客名と顧客TELと顧客住所は一意にきまるだめです。

では、第3正規化をしてみましょう。

TABLE: 売上 Primary Key:注文番号、商品ID

注文番号 注文年月日 商品ID 数量 顧客ID
1001 2020/12/20 K101 3 P501
1001 2020/12/20 K112 2 P501
1001 2020/12/20 K126 1 P501
1002 2020/12/21 Y516 2 P905
1002 2020/12/21 Y842 3 P905




TABLE: 商品 Primary Key:商品ID

商品ID 商品名 単価
K101 うまい棒 10
K112 がりがりくん 60
K126 チップスター 150
Y516 とまと 90
Y842 きゅうり 30




TABLE: 顧客 Primary Key:顧客ID

顧客ID 顧客名 顧客TEL 顧客住所
P501 岡氏 好男 0000-00-0000 東京都
P501 岡氏 好男 0000-00-0000 東京都
P501 岡氏 好男 0000-00-0000 東京都
P905 野菜 好子 1111-11-1111 埼玉県
P905 野菜 好子 1111-11-1111 埼玉県

これで第3正規形まで完成です。







以上、3回にわたり正規形の説明でした。

【SQL Server(連載)】正規化(第2正規化) -35-

www.pon-x.jp

前回の続き

今回は、第2正規化についてのはなしです。

第2正規化

前回、第1正規化を行い以下のようにテーブルを設計してきました。

注文番号 注文年月日 商品ID 商品名 単価 数量 顧客ID 顧客名 顧客TEL 顧客住所
1001 2020/12/20 K101 うまい棒 10 3 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K112 がりがりくん 60 2 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K126 チップスター 150 1 P501 岡氏 好男 0000-00-0000 東京都
1002 2020/12/21 Y516 とまと 90 2 P905 野菜 好子 1111-11-1111 埼玉県
1002 2020/12/21 Y842 きゅうり 30 3 P905 野菜 好子 1111-11-1111 埼玉県

上記の形式で、リレーショナルデータベースとしては扱えるのですが、まだこれではメンテナンス効率の悪い構造ですので、引き続き正規化を進めていきます。

第2正規化では、主キーに従属するカラムを別のテーブルに分離してあげることを目的とします。

関数従属性

一方の値が決まるともう一方の値も決まる関係を関数従属性といいます。
その関係のなかで主キー全てのカラムを用いて値が決まる関係を完全従属、主キーの一部のカラムによって値が決まる関係を部分従属といいます。
では、関数従属性の考え方を用いて、カラムを分離してみます。

TABLE: 売上 Primary Key:注文番号、商品ID

注文番号 注文年月日 商品ID 数量 顧客ID 顧客名 顧客TEL 顧客住所
1001 2020/12/20 K101 3 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K112 2 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K126 1 P501 岡氏 好男 0000-00-0000 東京都
1002 2020/12/21 Y516 2 P905 野菜 好子 1111-11-1111 埼玉県
1002 2020/12/21 Y842 3 P905 野菜 好子 1111-11-1111 埼玉県

TABLE: 商品 Primary Key:商品ID

商品ID 商品名 単価
K101 うまい棒 10
K112 がりがりくん 60
K126 チップスター 150
Y516 とまと 90
Y842 きゅうり 30







以上、今回はここまで。
次回は第3正規化をやります。

【SQL Server(連載)】正規化(第1正規化) -34-

www.pon-x.jp

前回の続き

今回からテーブル設計についての話になります。

正規化と正規形

リレーショナルデータベースをここまでやってきて、おおよそテーブル構造についても想像できるようになったかとおもいます。
一方で、テーブルを作るということもやってきたわけですが、どのような手順でテーブルを設計していくべきかということをしっかりと確認していきたいと思います。

例えば、リレーショナルデータベースを知らない人がEXCELなどでデータを書き並べていった場合、あたりまえですがリレーショナルデータベースにふさわしくない形式になっているかと思います。
この形式を非正規形といいます。
データベース設計者はこの非正規形のデータベースをリレーショナルデータベースとして扱える形式である正規形に設計しなおす必要があります。
この正規形にリメイクする処理を、正規化というわけです。

正規化には、第1正規化から第5正規化までありますが、実務においてはほぼ第3正規化までが必須となっているので、本ブログでも第3正規化まで紹介することにいたします。

今回の内容はだ1正規化です。

第1正規化

上記でも触れましたが、非正規形のデータベースを第1正規形に変換することを第1正規化といいます。

第1正規化とは、以下の処理を行うものをいいます。

  1. 繰り返しのカラムを別テーブルに分離
  2. キーを設定
  3. 導出項目を削除

では、ひとつひとつ見ていきましょう。

繰り返しのカラムを別テーブルに分離

まず、非正規形のデータを確認してみましょう。 例えば、こんなデータを例とします。

注文番号 注文年月日 商品名 単価 数量 合計金額 商品名 単価 数量 合計金額 商品名 単価 数量 合計金額 顧客ID 顧客名 顧客TEL 顧客住所
1001 2020/12/20 うまい棒 10 3 30 がりがりくん 60 2 120 チップスター 150 1 150 P501 岡氏 好男 0000-00-0000 東京都
1002 2020/12/21 とまと 90 2 180 きゅうり 21 30 60 P905 野菜 好子 1111-11-1111 埼玉県

上記の形式だと商品名、単価、数量が繰り返し項目になっています。
なんで、これだとリレーショナルデータベースにとって好ましくないかというと、顧客が1回の買い物で商品を最大いくつかうかということは想像つかないからです。
リレーショナルデータベースは、テーブルごとのカラムを事前に用意しておいて、データとしてレコードを増やしていくとい構造です。
なので、上記は非正規形であるといえるのです。
上記を改善するとこんな感じです。

注文番号 注文年月日 商品ID 商品名 単価 数量 合計金額 顧客ID 顧客名 顧客TEL 顧客住所
1001 2020/12/20 K101 うまい棒 10 3 30 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K112 がりがりくん 60 2 120 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K126 チップスター 150 1 150 P501 岡氏 好男 0000-00-0000 東京都
1002 2020/12/21 Y516 とまと 90 2 180 P905 野菜 好子 1111-11-1111 埼玉県
1002 2020/12/21 Y842 きゅうり 30 3 90 P905 野菜 好子 1111-11-1111 埼玉県

繰り返しカラムをまとめることができました。

キーの設定

上記の正規化過程で、商品IDカラムを追加しました。
非正規形のときは注文番号だけでユニークになったが、繰り返しカラムを除外することで、注文番号ともうひとつの2カラムでユニークにする必要があるためです。
※商品名のような名詞は必ずユニークになるとは言えないので、基本的にはキーに指定しません。

今回の場合、注文番号と商品IDでプライマリーキーに指定するのがよいでしょう。

導出項目を削除する。

導出項目とは、他のカラム(他のテーブルのカラムでもよい)を用いて算出できる値です。
つまり、ここでは単価と数量の積で求められる合計金額をさします。
わざわざカラムをつくらなくても、必要な時に演算させてあげればよいということです。

削除するとこんな感じになります。

注文番号 注文年月日 商品ID 商品名 単価 数量 顧客ID 顧客名 顧客TEL 顧客住所
1001 2020/12/20 K101 うまい棒 10 3 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K112 がりがりくん 60 2 P501 岡氏 好男 0000-00-0000 東京都
1001 2020/12/20 K126 チップスター 150 1 P501 岡氏 好男 0000-00-0000 東京都
1002 2020/12/21 Y516 とまと 90 2 P905 野菜 好子 1111-11-1111 埼玉県
1002 2020/12/21 Y842 きゅうり 30 3 P905 野菜 好子 1111-11-1111 埼玉県







以上、今回はここまで。
次回は第2正規化をやります。

【SQL Server(連載)】ストアドプロシージャ -33-

www.pon-x.jp

前回の続き

今回はストアドプロシージャの説明です。

ストアドプロシージャ

ストアドプロシージャとは、処理をまとめてひとつにして保存するものです。
前回まで、複数の処理を重ねて処理する例をたくさんやってきましたが、それらを実行するたびにコードにおこしていたのでは大変ですよね。
そんなときに解決してくれるものです。

使い方は処理の前に以下を記述するだけです。

CREATE PROCEDURE [ストアドプロシージャの名称]

    [引数][データ型],
    [引数][データ型],
・・・

AS

あとは上記いかに必要な処理を書いていくだけです。

ちなみに、作成済みストアドプロシージャを変更する際は、CREATEをALTERにするだけです。
こんなかんじ

ALTER PROCEDURE [ストアドプロシージャの名称]

    [引数][データ型],
    [引数][データ型],
・・・

AS

実際に試してみる

前回の処理に対して1点だけ変更を加えてをストアドプロシージャに保存してみます。 (引数に@PersonTypeを指定して、カーソルに格納するためのSELECT文のWHERE句に指定してあげることにしました。)
こんなかんじ


CREATE PROCEDURE TEST_PROCEDURE

    @PersonType NVARCHAR(2)

AS

IF OBJECT_ID(N'tempdb..#TEMP_TABLE', N'U') IS NOT NULL
    DROP TABLE #TEMP_TABLE

CREATE TABLE #TEMP_TABLE(
    ID INT Primary Key,
    FULLNAME NVARCHAR(128),
    NAME_LENGTH INT,
    MAX_LENGTH BIT
)

DECLARE @ID INT
DECLARE @F_NAME NVARCHAR(32)
DECLARE @M_NAME NVARCHAR(32)
DECLARE @L_NAME NVARCHAR(32)
DECLARE @MAX_LENGTH INT

SET @MAX_LENGTH = 0

DECLARE crTest CURSOR FOR
   SELECT 
        BusinessEntityID,
        FirstName,
        MiddleName,
        LastName
   FROM Person.Person
   WHERE PersonType = @PersonType

OPEN crTest

FETCH NEXT FROM crTest
INTO 
    @ID,
    @F_NAME,
    @M_NAME,
    @L_NAME

WHILE @@FETCH_STATUS = 0
BEGIN

   INSERT INTO #TEMP_TABLE
   VALUES(
        @ID,
        @F_NAME + ' ' + ISNULL(@M_NAME,'') + ' ' + @L_NAME,
        LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME),
        'false'
   )

   IF LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME) > @MAX_LENGTH
        SET @MAX_LENGTH = LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME)

   FETCH NEXT FROM crTest
   INTO 
        @ID,
        @F_NAME,
        @M_NAME,
        @L_NAME

END

CLOSE crTest
DEALLOCATE crTest



UPDATE #TEMP_TABLE
SET MAX_LENGTH = 'true'
WHERE NAME_LENGTH = @MAX_LENGTH


SELECT * FROM #TEMP_TABLE ORDER BY 4 desc

作成したストアドプロシージャはオブジェクトエクスプローラーで存在を確認できます。
f:id:hanabusa-snow:20201219084215p:plain

ちなみにここから変更ボタンをおすとALTER PROCEDUREで開いてくれるので便利です。
f:id:hanabusa-snow:20201219084329p:plain

実行してみる

保存されたストアドプロシージャは以下のように実行できます。

EXEC [dbo].[TEST_PROCEDURE] 'EM'

最後の’EM’は引数に対して、値を指定してあげています。
今回はWHERE句に代入される値ということになりますね。

結果はこんな感じ。
f:id:hanabusa-snow:20201219084517p:plain







以上、今回はここまで。

【SQL Server(連載)】カーソルの応用 -32-

www.pon-x.jp

前回の続き

今回は、カーソルと一時テーブルを組み合わせた使い方を紹介します。

カーソルと一時テーブル

例えば、SELECT文で出力したいのだけれどもものすごく複雑な構造になってしまう場合、一時テーブルでイメージしていた構造をつくってあげて、それに対してカーソルを用いてデータをインポートし、最後に一時テーブルを表示してあげるという手法が考えられます。

では、やってみましょう。
前回同様に、Person.Personテーブルにおいて、フルネームの字数を数えるというカーソルにおいて、一時テーブルに情報を追加していき、最後に表示するというものです。

IF OBJECT_ID(N'tempdb..#TEMP_TABLE', N'U') IS NOT NULL
    DROP TABLE #TEMP_TABLE

CREATE TABLE #TEMP_TABLE(
    ID INT Primary Key,
    FULLNAME NVARCHAR(128),
    NAME_LENGTH INT,
    MAX_LENGTH BIT
)

DECLARE @ID INT
DECLARE @F_NAME NVARCHAR(32)
DECLARE @M_NAME NVARCHAR(32)
DECLARE @L_NAME NVARCHAR(32)
DECLARE @MAX_LENGTH INT

SET @MAX_LENGTH = 0

DECLARE crTest CURSOR FOR
   SELECT 
        BusinessEntityID,
        FirstName,
        MiddleName,
        LastName
   FROM Person.Person

OPEN crTest

FETCH NEXT FROM crTest
INTO 
    @ID,
    @F_NAME,
    @M_NAME,
    @L_NAME

WHILE @@FETCH_STATUS = 0
BEGIN

   INSERT INTO #TEMP_TABLE
   VALUES(
        @ID,
        @F_NAME + ' ' + ISNULL(@M_NAME,'') + ' ' + @L_NAME,
        LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME),
        'false'
   )

   IF LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME) > @MAX_LENGTH
        SET @MAX_LENGTH = LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME)

   FETCH NEXT FROM crTest
   INTO 
        @ID,
        @F_NAME,
        @M_NAME,
        @L_NAME

END

CLOSE crTest
DEALLOCATE crTest



UPDATE #TEMP_TABLE
SET MAX_LENGTH = 'true'
WHERE NAME_LENGTH = @MAX_LENGTH


SELECT * FROM #TEMP_TABLE ORDER BY 4 desc

f:id:hanabusa-snow:20201217110446p:plain

構文説明

IF OBJECT_ID(N'tempdb..#TEMP_TABLE', N'U') IS NOT NULL
    DROP TABLE #TEMP_TABLE

CREATE TABLE #TEMP_TABLE(
    ID INT Primary Key,
    FULLNAME NVARCHAR(32),
    NAME_LENGTH INT,
    MAX_LENGTH BIT
)

ここでは、一時テーブルを作っています。

  1. ID ・・・BusinessEntityIDを入れるものです。
  2. FULLNAME ・・・フルネームを入れるものです。
  3. NAME_LENGTH ・・・ フルネームの字数を入れるものです。
  4. MAX_LENGTH BIT ・・・ 最大文字数のレコードは1、そうでないレコードには0を入れます。

カーソル部分は前回同様なので割愛します。

では、つづきの説明です。

   INSERT INTO #TEMP_TABLE
   VALUES(
        @ID,
        @F_NAME + ' ' + ISNULL(@M_NAME,'') + ' ' + @L_NAME,
        LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME),
        'false'
   )

INSERT INTOで1レコードずつ情報をいれます。
なお、MAX_LENGTHはひとまずすべてfalseを入れておきます。

   IF LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME) > @MAX_LENGTH
        SET @MAX_LENGTH = LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME)

@MAX_LENGTHとフルネーム文字数と比較して、フルネーム文字数が@MAX_LENGTHよりおおきければ、@MAX_LENGTHにフルネーム文字数をいれます。(なお@MAX_LENGTHは初期値を0としています)

UPDATE #TEMP_TABLE
SET MAX_LENGTH = 'true'
WHERE NAME_LENGTH = @MAX_LENGTH

@MAX_LENGTHはフルネーム文字数の最大値がとれているので、そのレコードをWHERE句で抽出し、対象のMAX_LENGTHをtrueに更新します。

SELECT * FROM #TEMP_TABLE ORDER BY 4 desc

表示します。

以上、こんなかんじで自由な一時テーブルがつくれます。
さまざまなアプリケーション開発をする場合は、たまに複雑な出力が求められるので必要になることがあるかも!?

以上、今回はここまで。

【SQL Server(連載)】カーソル -31-

www.pon-x.jp

前回の続き

今回はカーソルについて説明をしていきます。

カーソル

カーソルとは1行ずつデータを取り出してループ処理のなかでデータをハンドリングしていくことを目的とします。

では、さっそくサンプルを示してみたいと思います。 以下は、Person.PersonテーブルからBusinessEntityIDとFirstNameとMiddleNameとLastNameを1行ずつ取り出して表示し、最後にFirstNameとMiddleNameとLastNameの文字数の合計が一番多いレコードについて。BusinessEntityIDをPrint表示するという処理になります。

DECLARE @ID INT
DECLARE @F_NAME NVARCHAR(32)
DECLARE @M_NAME NVARCHAR(32)
DECLARE @L_NAME NVARCHAR(32)
DECLARE @MAX_LENGTH INT
DECLARE @TEMP_ID NVARCHAR(128)

SET @MAX_LENGTH = 0
DECLARE crTest CURSOR FOR
   SELECT 
        BusinessEntityID,
        FirstName,
        MiddleName,
        LastName
   FROM Person.Person

OPEN crTest

FETCH NEXT FROM crTest
INTO 
    @ID,
    @F_NAME,
    @M_NAME,
    @L_NAME

WHILE @@FETCH_STATUS = 0
BEGIN

   PRINT 'BusinessEntityID : ' + CONVERT(VARCHAR,@ID)
   PRINT 'Name : ' + @F_NAME + '_' + ISNULL(@M_NAME,'') + ' ' + @L_NAME
   PRINT '#---------------------#'

   IF LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME) > @MAX_LENGTH
        BEGIN
            SET @TEMP_ID = CONVERT(VARCHAR,@ID)
            SET @MAX_LENGTH = LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME)
        END
   ELSE IF LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME) = @MAX_LENGTH
        BEGIN
            SET @TEMP_ID = @TEMP_ID + ',' + CONVERT(VARCHAR,@ID)
        END


   FETCH NEXT FROM crTest
   INTO 
        @ID,
        @F_NAME,
        @M_NAME,
        @L_NAME

END

CLOSE crTest
DEALLOCATE crTest


PRINT '##########################'

PRINT @TEMP_ID

PRINT '##########################'

こんなかんじに出力できました。
f:id:hanabusa-snow:20201216102713p:plain

コードの説明

DECLARE crTest CURSOR FOR
   SELECT 
        BusinessEntityID,
        FirstName,
        MiddleName,
        LastName
   FROM Person.Person

上記の説明でカーソルを定義してあげています。
SELECT文の結果を保存しているようなイメージですね。

OPEN crTest

上記で、作成したカーソルを開きます。

FETCH NEXT FROM crTest
INTO 
    @ID,
    @F_NAME,
    @M_NAME,
    @L_NAME

上記で、カーソルを1行進めます。
つまり、最初の行を取り出して変数に入れるということをしています。

WHILE @@FETCH_STATUS = 0

@@FETCH_STATUS は0 のとき、フェッチが正常に実行できたということ、かみくだくと次のデータが取り出せたということになるので、その間はループを繰り返すという処理になります。

   IF LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME) > @MAX_LENGTH
        BEGIN
            SET @TEMP_ID = CONVERT(VARCHAR,@ID)
            SET @MAX_LENGTH = LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME)
        END
   ELSE IF LEN(@F_NAME) + LEN(ISNULL(@M_NAME,'')) + LEN(@L_NAME) = @MAX_LENGTH
        BEGIN
            SET @TEMP_ID = @TEMP_ID + ',' + CONVERT(VARCHAR,@ID)
        END

@MAX_LENGTHは初期値に0を入れてあります。
文字列の長さが@MAX_LENGTHよりおおきければ、@TEMP_IDにBusinessEntityIDを上書きし、さらに、@MAX_LENGTHを文字列の長さに書き換えます。
文字列の長さは@MAX_LENGTHと同じであれば、、@TEMP_IDにBusinessEntityIDを追記します。

   FETCH NEXT FROM crTest
   INTO 
        @ID,
        @F_NAME,
        @M_NAME,
        @L_NAME

上記はさらにカーソルを1行進めます。
ここで進めないとカーソルが進まないまま処理を繰り返すので一生処理が終わりません。

CLOSE crTest
DEALLOCATE crTest

上記は、カーソルを閉じて、その次にカーソルを開放します。
開放しないとメモリを消費しっぱなしになるので注意しましょう。

PRINT '##########################'

PRINT @TEMP_ID

PRINT '##########################'

上記は最大文字数であった名前のBusinessEntityIDを表示しています。







以上です。結構難しくなってきましたがいかがだったでしょうか。
次回はカーソルの応用です。

【SQL Server(連載)】一時テーブル -30-

www.pon-x.jp

前回の続き

今回は、一時テーブルの扱い方について説明します。

一時テーブル

その処理の中において、仮想にデータを保持したいときに扱うのが、一時テーブルです。
一時テーブルは実際にはテーブルを作成せず(実際は tempdbに作成される)に、その処理の中で一時的に作られるテーブルを言います。

一時テーブルは、同一セッション内ののみ有効な「ローカル一時テーブル」と、その他のセッションでも引き継がれるな「グローバル一時テーブル」があり、作り方が異なります。

ローカル一時テーブル

ローカル一時テーブルは、テーブル名の先頭に#をつけます。
例えばこんな感じです。

CREATE TABLE #TEMP_TABLE(
    NUM INT,
    TXT NVARCHAR(10)
)

では、作成した一時テーブルを参照してみましょう。
SSMSで別のタブを開いて以下のSQLを実行してみてください。

SELECT * FROM #TEMP_TABLE

以下の通りエラー表示になり出力はできません。 f:id:hanabusa-snow:20201215085912p:plain

グローバル一時テーブル

グローバル一時テーブルは、テーブル名の先頭に##をつけます。
例えばこんな感じです。

CREATE TABLE ##TEMP_TABLE(
    NUM INT,
    TXT NVARCHAR(10)
)

では、また作成した一時テーブルを参照してみましょう。
SSMSで別のタブを開いて以下のSQLを実行してみてください。

SELECT * FROM ##TEMP_TABLE

以下の通りセッションをまたいでも出力できることが確認できました。
f:id:hanabusa-snow:20201215090315p:plain

一時テーブルの削除

通常のテーブル同様にDROPで削除が可能です。
ただし、通常のテーブルと違うのは一時テーブルはあくまで一時つくるもので、処理毎に作成することになるでしょうから、頻繁にテーブルの作成処理が行われることになろうと思います。
その時に、一時テーブルが存在していれば問題なく削除処理ができるのですが、存在しない場合に削除処理を行うとエラーになり以後の処理に至りません。
そこで、一時テーブルを削除する前に、テーブルの存在チェックを行うことをお勧めします。
こんな感じです。

IF OBJECT_ID(N'tempdb..#TEMP_TABLE', N'U') IS NOT NULL
    DROP TABLE #TEMP_TABLE

CREATE TABLE #TEMP_TABLE(
    NUM INT,
    TXT NVARCHAR(10)
)

これでなんど実行してもエラー出力になることはありません。

以下、適当に一時テーブルで遊んでみました。

IF OBJECT_ID(N'tempdb..#TEMP_TABLE', N'U') IS NOT NULL
    DROP TABLE #TEMP_TABLE

CREATE TABLE #TEMP_TABLE(
    NUM INT,
    TXT NVARCHAR(20)
)

DECLARE @NUM INT
DECLARE @VALUE BIGINT

SET @NUM = 1

WHILE @NUM < 10
    BEGIN
        SET @VALUE = POWER(10, @NUM)

        INSERT INTO #TEMP_TABLE
        VALUES
        (RAND() * @VALUE, 'UNDER ' + CONVERT(VARCHAR, @VALUE))
        SET @NUM += 1
    END


SELECT * FROM #TEMP_TABLE

0以上、かつ10の累乗のデータを追加した一時テーブルを作成します。
作成毎に値が変わるので、試してみてください。

こんなかんじ。 f:id:hanabusa-snow:20201215091934p:plain







以上、今回はここまで