このエントリは Tsurugi Advent Calendar 2025 の19日目のエントリです。前日は id:hishidama さんによる「 Tsurugi JDBCの使い方 - シャットダウンオプション 」でした。
取り上げる題材はTsurugiのSQLでは大文字小文字の区別はどのようになっているかというものです。結論を先に挙げると次の通りです。
- SQLキーワード (
SELECTやFROMなど) は大文字小文字を区別しない - ユーザーが定義するデータベースオブジェクト名 (テーブル名や列名など) はデフォルト設定では大文字小文字を区別し、小文字に正規化する設定が存在する
- その設定は
tsurugi.iniの[sql]セクションに存在するlowercase_regular_identifiersで、デフォルトではfalseに設定されている - ただし上記設定に関わらず、引用符で囲まれた識別子は大文字小文字を区別する
- その設定は
多くのRDBMSでは引用していないデータベースオブジェクト名は大文字小文字を区別しないため、意外とつまずくかもしれないポイントです。以下で具体的な挙動を見ていきます。
デフォルト設定での動き
Tsurugiをインストール直後の tsurugi.ini の [sql] セクションの記述は次のようになっています。
[sql]
#commit_response=STORED
#default_partitions=5
#lowercase_regular_identifiers=false
#max_result_set_writers=64
#scan_block_size=100
#scan_default_parallel=4
#scan_yield_interval=1
#stealing_enabled=true
#thread_pool_size=
lowercase_regular_identifiers の設定がコメントアウトされていますが、デフォルトの設定値はここに記述されている false です。
この状態で次のDDLを実行してテーブルを作ります。
create table Case_Sample ( ID bigint primary key, Col_1 varchar(*) not null );
tgsqlコンソールでテーブル一覧を確認すると、テーブル名に設定した大文字小文字が反映されていますね。
tgsql> \show table Case_Sample
ここでテーブル名を全て小文字にして \show table コマンドを実行してみるとテーブルが見つかりません。
大文字小文字を正しく記述することでテーブル定義を確認することができます。
tgsql> \show table case_sample 'case_sample' table not found tgsql> \show table Case_Sample databaseName=null schemaName=null tableName='Case_Sample' (0) ID: BIGINT NOT NULL (1) Col_1: VARCHAR(*) NOT NULL primary key=[ID]
SQLの実行についても同様に、テーブル名や列名について大文字小文字を正しく記述する必要があります。
tgsql> insert into case_sample (id, col_1) values (1, 'test'); start transaction implicitly. option=[ type: OCC label: "tgsql-implicit-transaction2025-12-09 00:29:50.856+09:00" ] SYMBOL_ANALYZE_EXCEPTION (SQL-03004: compile failed with error:table_not_found message:"table "case_sample" is not found" location:<input>:1:13+11) transaction rollback finished implicitly. tgsql> insert into Case_Sample (ID, Col_1) values (1, 'test'); start transaction implicitly. option=[ type: OCC label: "tgsql-implicit-transaction2025-12-09 00:30:22.674+09:00" ] (1 row inserted) transaction commit(DEFAULT) finished implicitly. tgsql> select id, col_1 from case_sample; start transaction implicitly. option=[ type: OCC label: "tgsql-implicit-transaction2025-12-09 00:31:00.586+09:00" ] SYMBOL_ANALYZE_EXCEPTION (SQL-03004: compile failed with error:table_not_found message:"table "case_sample" is not found" location:<input>:1:23+11) transaction rollback finished implicitly. tgsql> select ID, Col_1 from Case_Sample; start transaction implicitly. option=[ type: OCC label: "tgsql-implicit-transaction2025-12-09 00:31:28.003+09:00" ] [ID: BIGINT, Col_1: VARCHAR(*)] [1, test] (1 row) transaction commit(DEFAULT) finished implicitly.
lowercase_regular_identifiers に true を設定した場合の動き
先にも述べたように多くのRDBMSでは引用していないデータベースオブジェクトは大文字小文字を区別しないため、このデフォルトの動きは違和感を感じる方も多いかもしれません。
そこで tsurugi.ini の [sql] セクションに存在する lowercase_regular_identifiers の設定を true に変更してみます (先程作成したテーブルを削除した前提で説明しています) 。
[sql]
#commit_response=STORED
#default_partitions=5
lowercase_regular_identifiers=true
#max_result_set_writers=64
#scan_block_size=100
#scan_default_parallel=4
#scan_yield_interval=1
#stealing_enabled=true
#thread_pool_size=
先程と同様に次のDDLでテーブルを作成してみます。
create table Case_Sample ( ID bigint primary key, Col_1 varchar(*) not null );
tgsqlコンソールでテーブル一覧を確認するとテーブル名は小文字になっています。それは先程の設定が「SQLで指定したデータベースオブジェクトの識別子は小文字に正規化する」という設定になっているからです。
tgsql> \show table case_sample
\show table コマンドを実行すると列名も小文字になっていることが確認できます。
tgsql> \show table case_sample databaseName=null schemaName=null tableName='case_sample' (0) id: BIGINT NOT NULL (1) col_1: VARCHAR(*) NOT NULL primary key=[id]
SQLを実行してみると、大文字小文字どちらでも動きます。ただし、識別子を引用する場合はこの設定であっても区別します。 この挙動は概ね PostgreSQLと同じ挙動 になります。
tgsql> insert into case_sample (id, col_1) values (1, 'test'); start transaction implicitly. option=[ type: OCC label: "tgsql-implicit-transaction2025-12-09 00:26:42.940+09:00" ] (1 row inserted) transaction commit(DEFAULT) finished implicitly. tgsql> select id, col_1 from case_sample; start transaction implicitly. option=[ type: OCC label: "tgsql-implicit-transaction2025-12-09 00:27:02.509+09:00" ] [id: BIGINT, col_1: VARCHAR(*)] [1, test] (1 row) transaction commit(DEFAULT) finished implicitly. tgsql> SELECT ID, COL_1 FROM CASE_SAMPLE; start transaction implicitly. option=[ type: OCC label: "tgsql-implicit-transaction2025-12-09 00:28:08.814+09:00" ] [id: BIGINT, col_1: VARCHAR(*)] [1, test] (1 row) transaction commit(DEFAULT) finished implicitly. tgsql> select Id, Col_1 from Case_Sample; start transaction implicitly. option=[ type: OCC label: "tgsql-implicit-transaction2025-12-09 00:29:01.847+09:00" ] [id: BIGINT, col_1: VARCHAR(*)] [1, test] (1 row) transaction commit(DEFAULT) finished implicitly. tgsql> select Id, Col_1 from "Case_Sample"; start transaction implicitly. option=[ type: OCC label: "tgsql-implicit-transaction2025-12-09 00:36:58.053+09:00" ] SYMBOL_ANALYZE_EXCEPTION (SQL-03004: compile failed with error:table_not_found message:"table "Case_Sample" is not found" location:<input>:1:23+13) transaction rollback finished implicitly.
ちなみに \show table コマンドの場合は設定に関わらず大文字小文字を区別するので注意してください。これはSQLではなくtgsqlが備えるコマンドです。
tgsql> \show table Case_Sample 'Case_Sample' table not found
まとめ
まとめると、Tsurugiはデフォルトでデータベースオブジェクト名の大文字小文字をSQL上で区別します。他のRDBMSに慣れていると違和感を感じる方が多いかもしれませんが、Java系のORマッパーを使っている場合などCamelCaseの識別子を使いたい場合にはこの方がいいと感じる方もいるかもですね。
個人的な意見としては、混乱しないように次のどちらかのルールで運用した方がいいと思います。
lowercase_regular_identifiersをtrueに設定して運用する- デフォルト設定で運用する場合、データベースオブジェクト名は小文字で統一するかCamelCaseにする
(参考) 他のRDBMSではどのようになっているの?
先程も述べたように lowercase_regular_identifiers に true を設定した場合の動きは概ねPostgreSQLと同じです。
SQL標準では大文字に正規化することになっており、Oracleなどはそのような挙動になっています。
参考までに他のRDBMSでのこの動きについて説明しているドキュメントのリンクを挙げておきます。MySQLはデータベースオブジェクトをファイルとして保存するため、OSやファイルシステムによって挙動が変わることで有名ですね。