ScalarDB SQL 文法
このページは英語版のページが機械翻訳されたものです。英語版との間に矛盾または不一致がある場合は、英語版を正としてください。
- DDL
- DML
- DCL
- CREATE USER
- ALTER USER
- DROP USER
- GRANT
- REVOKE
- CREATE ROLE
- DROP ROLE
- GRANT ... TO ROLE
- REVOKE ... FROM ROLE
- GRANT ROLE
- REVOKE ROLE
- REVOKE ADMIN OPTION
- CREATE ABAC_POLICY
- ENABLE ABAC_POLICY
- DISABLE ABAC_POLICY
- CREATE ABAC_LEVEL
- DROP ABAC_LEVEL
- CREATE ABAC_COMPARTMENT
- DROP ABAC_COMPARTMENT
- CREATE ABAC_GROUP
- DROP ABAC_GROUP
- SET ABAC_LEVEL
- ADD ABAC_COMPARTMENT
- REMOVE ABAC_COMPARTMENT
- ADD ABAC_GROUP
- REMOVE ABAC_GROUP
- DROP ABAC_USER_TAG_INFO
- CREATE ABAC_NAMESPACE_POLICY
- ENABLE ABAC_NAMESPACE_POLICY
- DISABLE ABAC_NAMESPACE_POLICY
- CREATE ABAC_TABLE_POLICY
- ENABLE ABAC_TABLE_POLICY
- DISABLE ABAC_TABLE_POLICY
- Others
- USE
- BEGIN
- START TRANSACTION
- JOIN
- PREPARE
- VALIDATE
- COMMIT
- ROLLBACK
- ABORT
- SET MODE
- SHOW NAMESPACES
- SHOW TABLES
- DESCRIBE
- SUSPEND
- RESUME
- SHOW USERS
- SHOW GRANTS
- SHOW ROLES
- SHOW ROLE USERS
- SHOW ROLE GRANTS
- SHOW ABAC_POLICY
- SHOW ABAC_POLICIES
- SHOW ABAC_LEVEL
- SHOW ABAC_LEVELS
- SHOW ABAC_COMPARTMENT
- SHOW ABAC_COMPARTMENTS
- SHOW ABAC_GROUP
- SHOW ABAC_GROUPS
- SHOW ABAC_USER_TAG_INFO
- SHOW ABAC_NAMESPACE_POLICY
- SHOW ABAC_NAMESPACE_POLICIES
- SHOW ABAC_TABLE_POLICY
- SHOW ABAC_TABLE_POLICIES
- リテラル
DDL
CREATE NAMESPACE
テーブルは1つの名前空間に属しているため、テーブルを作成する前に名前空間を作成する必要があります。CREATE NAMESPACE コマンドは名前空間を作成します。
文法
CREATE NAMESPACE [IF NOT EXISTS] <namespace name> [WITH creation_options]
creation_options: <option name>=<option value> [AND <option name>=<option value>] ...
creation_optionsの詳細については、作成オプションを参照してください。
例
CREATE NAMESPACE の例は次のとおりです。
-- Create a namespace "ns"
CREATE NAMESPACE ns;
-- Create a namespace only if it does not already exist
CREATE NAMESPACE IF NOT EXISTS ns;
-- Create a namespace with options
CREATE NAMESPACE ns WITH 'option1' = 'value1' AND 'option2' = 'value2' AND 'option3' = 'value3';
CREATE NAMESPACE のステートメントオブジェクトを構築する例は次のとおりです。
// Create a namespace "ns"
CreateNamespaceStatement statement1 = StatementBuilder.createNamespace("ns").build();
// Create a namespace only if it does not already exist
CreateNamespaceStatement statement2 =
StatementBuilder.createNamespace("ns").ifNotExists().build();
// Create a namespace with options
CreateNamespaceStatement statement3 =
StatementBuilder.createNamespace("ns")
.withOption("option1", "value1")
.withOption("option2", "value2")
.withOption("option3", "value3")
.build();
CREATE TABLE
CREATE TABLE コマンドはテーブルを作成します。
ScalarDB データモデルの詳細については、ScalarDB 設計ドキュメントを参照してください。
文法
単一の列で構成される主キーを持つテーブルを作成します。
CREATE TABLE [IF NOT EXISTS] [<namespace name>.]<table name> (
<primary key column name> data_type PRIMARY KEY,
<column name> data_type,
...
) [WITH creation_options]
data_type: BOOLEAN | INT | BIGINT | FLOAT | DOUBLE | TEXT | BLOB | DATE | TIME | TIMESTAMP | TIMESTAMPTZ
creation_options: <option name>=<option value> [AND <option name>=<option value>] ...
- 主キー以外の列に
ENCRYPTEDを指定して、それらの列のデータを暗号化できます。 - 作成オプションの詳細については、作成オプションを参照してください。
1つのパーティションキー列と複数のクラスタリングキー列で構成される主キーを持つテーブルを作成します。
CREATE TABLE [IF NOT EXISTS] [<namespace name>.]<table name> (
<partition key column name> data_type,
<clustering key column name> data_type,
...,
<column name> data_type [ENCRYPTED],
...,
PRIMARY KEY (<partition key column name>, <clustering key column name> [, <clustering key column name>] ...)
) [WITH [clustering_order_definition [AND creation_options]] | creation_options]
clustering_order_definition: CLUSTERING ORDER BY (<clustering key column name> [clustering_order] [, <clustering key column name> [clustering_order]] ...)
clustering_order: ASC | DESC
clustering_orderを省略すると、デフォルトのクラスタリング順序ASCが使用されます。
複数のパーティションキー列と複数のクラスタリングキー列で構成される主キーを持つテーブルを作成します。
CREATE TABLE [IF NOT EXISTS] [<namespace name>.]<table name> (
<partition key column name> data_type,
...,
<clustering key column name> data_type,
...,
<column name1> data_type [ENCRYPTED],
<column name2> data_type [ENCRYPTED],
...,
PRIMARY KEY ((<partition key column name> [, <partition key column name>] ...), <clustering key column name> [, <clustering key column name>] ...)
) [WITH [clustering_order_definition [AND creation_options]] | creation_options]
例
CREATE TABLE の例は次のとおりです。
-- Create a table with a primary key ("c1") and creation options
CREATE TABLE ns.tbl (
c1 INT PRIMARY KEY,
c2 TEXT,
c3 FLOAT,
c4 BIGINT,
c5 BOOLEAN
) WITH 'option1' = 'value1' AND 'option2' = 'value2' AND 'option3' = 'value3';
-- Create a table with a partition key ("c1") and a clustering key ("c2" and "c3") with clustering order definition only if it does not already exist
CREATE TABLE IF NOT EXISTS tbl (
c1 INT,
c2 TEXT,
c3 FLOAT,
c4 BIGINT,
c5 BOOLEAN,
PRIMARY KEY (c1, c2, c3)
) WITH CLUSTERING ORDER BY (c2 DESC, c3 ASC);
-- Create a table with a partition key ("c1", "c2") and a clustering key ("c3" and "c4") with clustering order definition and creation options
CREATE TABLE ns.tbl (
c1 INT,
c2 TEXT,
c3 FLOAT,
c4 BIGINT,
c5 BOOLEAN,
PRIMARY KEY ((c1, c2), c3, c4)
) WITH CLUSTERING ORDER BY (c3 DESC, c4 ASC) AND 'option1' = 'value1' AND 'option2' = 'value2' AND 'option3' = 'value3';
-- Create a table with a primary key ("c1") and encrypted columns ("c2", "c3", "c4", and "c5")
CREATE TABLE ns.tbl (
c1 INT PRIMARY KEY,
c2 TEXT ENCRYPTED,
c3 FLOAT ENCRYPTED,
c4 BIGINT ENCRYPTED,
c5 BOOLEAN ENCRYPTED
);
CREATE TABLE のステートメントオブジェクトを構築する例は次のとおりです。
// Create a table with a primary key ("c1") and creation options
CreateTableStatement statement1 =
StatementBuilder.createTable("ns", "tbl")
.withPartitionKey("c1", DataType.INT)
.withColumn("c2", DataType.TEXT)
.withColumn("c3", DataType.FLOAT)
.withColumn("c4", DataType.BIGINT)
.withColumn("c5", DataType.BOOLEAN)
.withOption("option1", "value1")
.withOption("option2", "value2")
.withOption("option3", "value3")
.build();
// Create a table with a partition key ("c1") and a clustering key ("c2" and "c3") with clustering order definition
CreateTableStatement statement2 =
StatementBuilder.createTable("tbl")
.ifNotExists()
.withPartitionKey("c1", DataType.INT)
.withClusteringKey("c2", DataType.TEXT)
.withClusteringKey("c3", DataType.FLOAT)
.withColumn("c4", DataType.BIGINT)
.withColumn("c5", DataType.BOOLEAN)
.withClusteringOrder("c2", ClusteringOrder.DESC)
.withClusteringOrder("c3", ClusteringOrder.ASC)
.build();
// Create a table with a partition key ("c1", "c2") and a clustering key ("c3" and "c4") with clustering order definition and creation options
CreateTableStatement statement3 =
StatementBuilder.createTable("ns", "tbl")
.withPartitionKey("c1", DataType.INT)
.withPartitionKey("c2", DataType.TEXT)
.withClusteringKey("c3", DataType.FLOAT)
.withClusteringKey("c4", DataType.BIGINT)
.withColumn("c5", DataType.BOOLEAN)
.withClusteringOrder("c3", ClusteringOrder.DESC)
.withClusteringOrder("c4", ClusteringOrder.ASC)
.withOption("option1", "value1")
.withOption("option2", "value2")
.withOption("option3", "value3")
.build();
// Create a table with a primary key ("c1") and encrypted columns ("c2", "c3", "c4", and "c5")
CreateTableStatement statement4 =
StatementBuilder.createTable("ns", "tbl")
.withPartitionKey("c1", DataType.INT)
.withColumn("c2", DataType.TEXT, true)
.withColumn("c3", DataType.FLOAT, true)
.withColumn("c4", DataType.BIGINT, true)
.withColumn("c5", DataType.BOOLEAN, true)
.build();
CREATE INDEX
CREATE INDEX コマンドは、テーブルにセカンダリインデックスを作成します。
次の場合、テーブルにセカンダリインデックスを作成することはできません:
- 列が暗号化されている場合。
- テーブルが Object Storage 上にある場合。
文法
CREATE INDEX [IF NOT EXISTS] ON [<namespace name>.]<table name> (<column name>) [WITH creation_options]
creation_options: <option name>=<option value> [AND <option name>=<option value>] ...
creation_optionsの詳細については、作成オプションを参照してください。
例
CREATE INDEX の例は次のとおりです。
-- Create a secondary index on a column "c4" of a table "ns.tbl"
CREATE INDEX ON ns.tbl (c4);
-- Create a secondary index only if it does not already exist
CREATE INDEX IF NOT EXISTS ON tbl (c4);
-- Create a secondary index with options
CREATE INDEX ON ns.tbl (c4) WITH 'option1' = 'value1' AND 'option2' = 'value2' AND 'option3' = 'value3';
CREATE INDEX のステートメントオブジェクトを構築する例は次のとおりです。
// Create a secondary index on a column "c4" of a table "ns.tbl"
CreateIndexStatement statement1 =
StatementBuilder.createIndex().onTable("ns", "tbl").column("c4").build();
// Create a secondary index only if it does not already exist
CreateIndexStatement statement2 =
StatementBuilder.createIndex().ifNotExists().onTable("tbl").column("c4").build();
// Create a secondary index with options
CreateIndexStatement statement3 =
StatementBuilder.createIndex()
.onTable("ns", "tbl")
.column("c4")
.withOption("option1", "value1")
.withOption("option2", "value2")
.withOption("option3", "value3")
.build();
TRUNCATE TABLE
TRUNCATE TABLE コマンドはテーブルのすべての行を削除します。
文法
TRUNCATE TABLE [<namespace name>.]<table name>
例
TRUNCATE TABLE の例は次のとおりです。
-- Truncate a table "ns.tbl"
TRUNCATE TABLE ns.tbl;
TRUNCATE TABLE のステートメントオブジェクトを構築する例は次のとおりです。
// Truncate a table "ns.tbl"
TruncateTableStatement statement = StatementBuilder.truncateTable("ns", "tbl").build();
DROP INDEX
DROP INDEX コマンドはセカンダリインデックスを削除します。
文法
DROP INDEX [IF EXISTS] ON [<namespace name>.]<table name> (<column name>)
例
DROP INDEX の例は次のとおりです。
-- Drop a secondary index on a column "c4" of a table "ns.tbl"
DROP INDEX ON ns.tbl (c4);
-- Drop a secondary index only if it exists
DROP INDEX IF EXISTS ON tbl (c4);
DROP INDEX のステートメントオブジェクトを構築する例は次のとおりです。
// Drop a secondary index on a column "c4" of a table "ns.tbl"
DropIndexStatement statement1 =
StatementBuilder.dropIndex().onTable("ns", "tbl").column("c4").build();
// Drop a secondary index only if it exists
DropIndexStatement statement2 =
StatementBuilder.dropIndex().ifExists().onTable("ns", "tbl").column("c4").build();
DROP TABLE
DROP TABLE コマンドはテーブルを削除します。
文法
DROP TABLE [IF EXISTS] [<namespace name>.]<table name>
例
DROP TABLE の例は次のとおりです。
-- Drop a table "ns.tbl"
DROP TABLE ns.tbl;
-- Drop a table only if it exists
DROP TABLE IF EXISTS tbl;
DROP TABLE のステートメントオブジェクトを構築する例は次のとおりです。
// Drop a table "ns.tbl"
DropTableStatement statement1 = StatementBuilder.dropTable("ns", "tbl").build();
// Drop a table only if it exists
DropTableStatement statement2 = StatementBuilder.dropTable("ns", "tbl").ifExists().build();
DROP NAMESPACE
DROP NAMESPACE コマンドは名前空間を削除します。
文法
DROP NAMESPACE [IF EXISTS] <namespace name> [CASCADE]
例
DROP NAMESPACE の例は次のとおりです。
-- Drop a namespace "ns"
DROP NAMESPACE ns;
-- Drop a namespace only if it exists
DROP NAMESPACE IF EXISTS ns;
-- Drop a namespace with cascade
DROP NAMESPACE ns CASCADE;
DROP NAMESPACE のステートメン トオブジェクトを構築する例は次のとおりです。
// Drop a namespace "ns"
DropNamespaceStatement statement1 = StatementBuilder.dropNamespace("ns").build();
// Drop a namespace only if it exists
DropNamespaceStatement statement2 = StatementBuilder.dropNamespace("ns").ifExists().build();
// Drop a namespace with cascade
DropNamespaceStatement statement3 = StatementBuilder.dropNamespace("ns").cascade().build();
CREATE COORDINATOR TABLES
CREATE COORDINATOR TABLES コマンドは Coordinator テーブルを作成します。
文法
CREATE COORDINATOR TABLES [IF NOT {EXIST|EXISTS}] [WITH creation_options]
creation_options: <option name>=<option value> [AND <option name>=<option value>] ...
例
Examples of CREATE COORDINATOR TABLES are as follows:
-- Create coordinator tables
CREATE COORDINATOR TABLES;
-- Create coordinator tables only if they do not already exist
CREATE COORDINATOR TABLES IF NOT EXIST;
-- Create coordinator tables with options
CREATE COORDINATOR TABLES WITH 'option1' = 'value1' AND 'option2' = 'value2' AND 'option3' = 'value3';
CREATE COORDINATOR TABLES のステートメントオブジェクトを構築する例は次のとおりです。
// Create coordinator tables
CreateCoordinatorTablesStatement statement1 =
StatementBuilder.createCoordinatorTables().build();
// Create coordinator tables only if they do not already exist
CreateCoordinatorTablesStatement statement2 =
StatementBuilder.createCoordinatorTables().ifNotExist().build();
// Create coordinator tables with options
CreateCoordinatorTablesStatement statement3 =
StatementBuilder.createCoordinatorTables()
.withOption("option1", "value1")
.withOption("option2", "value2")
.withOption("option3", "value3")
.build();
TRUNCATE COORDINATOR TABLES
TRUNCATE COORDINATOR TABLES コマンドは Coordinator テーブルのすべての行を削除します。
文法
TRUNCATE COORDINATOR TABLES
例
TRUNCATE COORDINATOR TABLES のステートメントオブジェクトを構築する例を次に示します。
// Truncate coordinator tables
TruncateCoordinatorTablesStatement statement =
StatementBuilder.truncateCoordinatorTables().build();
DROP COORDINATOR TABLES
DROP COORDINATOR TABLES コマンドは Coordinator テーブルを削除します。
文法
DROP COORDINATOR TABLES [IF {EXIST|EXISTS}]
例
DROP COORDINATOR TABLES の例は次のとおりです。
-- Drop coordinator tables
DROP COORDINATOR TABLES;
-- Drop coordinator tables if they exist
DROP COORDINATOR TABLES IF EXIST;
DROP COORDINATOR TABLES のステートメントオブジェクトを構築する例は次のとおりです。
// Drop coordinator tables
DropCoordinatorTablesStatement statement1 = StatementBuilder.dropCoordinatorTables().build();
// Drop coordinator tables if they exist
DropCoordinatorTablesStatement statement2 =
StatementBuilder.dropCoordinatorTables().ifExist().build();
ALTER TABLE
ALTER TABLE コマンドはテーブルを変更します (例: 列の追加)。
ADD COLUMN
ADD COLUMN サブコマンドは、テーブルに新しい列を追加します。
文法
ALTER TABLE [<namespace name>.]<table name> ADD [COLUMN] [IF NOT EXISTS] <column name> data_type [ENCRYPTED]
data_type: BOOLEAN | INT | BIGINT | FLOAT | DOUBLE | TEXT | BLOB | DATE | TIME | TIMESTAMP | TIMESTAMPTZ
- 列に
ENCRYPTEDを指定して、その列のデータを暗号化できます。
例
ADD COLUMN の例は次のとおりです。
-- Add a new column "new_col" to "ns.tbl"
ALTER TABLE ns.tbl ADD COLUMN new_col INT;
-- Add a new encrypted column "new_col" to "ns.tbl"
ALTER TABLE ns.tbl ADD COLUMN new_col TEXT ENCRYPTED;
-- Add a new column only if it does not already exist
ALTER TABLE ns.tbl ADD COLUMN IF NOT EXISTS new_col INT;
ADD COLUMN のステートメントオブジェクトを構築する例は次のとおりです。
// Add a new column "new_col" to "ns.tbl"
AlterTableAddColumnStatement statement1 =
StatementBuilder.alterTable("ns", "tbl").addColumn("new_col", DataType.INT).build();
// Add a new encrypted column "new_col" to "ns.tbl"
AlterTableAddColumnStatement statement2 =
StatementBuilder.alterTable("ns", "tbl").addColumn("new_col", DataType.TEXT, true).build();
// Add a new column only if it does not already exist
AlterTableAddColumnStatement statement3 =
StatementBuilder.alterTable("ns", "tbl").addColumn("new_col", DataType.INT).ifNotExists().build();
テーブルに新しい列を追加する場合は、基盤となるストレージによって実行時間が大きく異なる可能性があるため、慎重に検討する必要があります。特にデータベースが本番環境で実行されている場合は、以下の点を考慮して適切に計画を立ててください。
- Cosmos DB for NoSQL および DynamoDB の場合: テーブルスキーマは変更されないため、列の追加はほぼ瞬時に行われます。別のテーブルに格納されているテーブルメタデータのみが更新されます。
- Cassandra の場合: 列を追加すると、スキーマメタデータのみが更新され、既存のスキーマレコードは変更されません。クラスタートポロジが実行時間の主な要因です。スキーマメタデータの変更は、ゴシッププロトコルを介して各クラスターノードに共有されます。このため、クラスターが大きいほど、すべてのノードが更新されるまでの時間が長くなります。
- リレーショナルデータベース (MySQL、Oracle など) の場合: 列の追加は、データベースエンジンによってはテーブルの再構築を引き起こす可能性があります。そのような場合、実行に長時間かかることがあります。
DROP COLUMN
DROP COLUMN サブコマンドは、テーブルから列を削除します。
文法
ALTER TABLE [<namespace name>.]<table name> DROP [COLUMN] [IF EXISTS] <column name>
例
DROP COLUMN の例は次のとおりです。
-- Drop a column "col1" from "ns.tbl"
ALTER TABLE ns.tbl DROP COLUMN col1;
-- Drop a column "col1" from "ns.tbl" only if it exists
ALTER TABLE ns.tbl DROP COLUMN IF EXISTS col1;
DROP COLUMN のステートメントオブジェクトを構築する例は次のとおりです。
// Drop a column "col1" from "ns.tbl"
AlterTableDropColumnStatement statement1 =
StatementBuilder.alterTable("ns", "tbl").dropColumn("col1").build();
// Drop a column "col1" from "ns.tbl" only if it exists
AlterTableDropColumnStatement statement2 =
StatementBuilder.alterTable("ns", "tbl").dropColumn("col1").ifExists().build();
次の場合、テーブルから列を削除することはできません。
- 列が パーティションキーまたはクラスタリングキーの一部である場合。
- テーブルが Cassandra を除く非 JDBC データベース上にある場合。
テーブルから列を削除する場合は、基盤となるストレージによって実行時間が大きく異なる可能性があるため、慎重に検討する必要があります。特にデータベースが本番環境で実行されている場合は、以下の点を考慮して適切に計画を立ててください。
- Cassandra の場合: 列を削除すると、スキーマメタデータのみが更新され、実際のデータは次のコンパクション時に削除されます。クラスタートポロジが実行時間の主な要因です。スキーマメタデータの変更は、ゴシッププロトコルを介して各クラスターノードに共有されます。このため、クラスターが大きいほど、すべてのノードが更新されるまでの時間が長くなります。
- リレーショナルデータベース (MySQL、Oracle など) の場合: 列の削除は、基盤となるリレーショナルデータベースに
ALTER TABLE ... DROP COLUMNを発行し、データベースによってはテーブルの再構築を引き起こす可能性があります。そのような場合、実行に長時間かかることがあります。
RENAME COLUMN
RENAME COLUMN サブコマンドは、テーブル内の列の名前を変更します。
文法
ALTER TABLE [<namespace name>.]<table name> RENAME COLUMN <old column name> TO <new column name>
例
RENAME COLUMN の例は次のとおりです。
-- Rename a column "old_col" to "new_col" in "ns.tbl"
ALTER TABLE ns.tbl RENAME COLUMN old_col TO new_col;
RENAME COLUMN のステートメントオブジェクトを構築する例は次のとおりです。
// Rename a column "old_col" to "new_col" in "ns.tbl"
AlterTableRenameColumnStatement statement1 =
StatementBuilder.alterTable("ns", "tbl").renameColumn("old_col", "new_col").build();
次の場合、テーブルの列の名前を変更することはできません。
- テーブルが Cassandra を除く非 JDBC データベース上にある場合。
- Cassandra の場合、列がパーティションキーまたはクラスタリングキーの一部でない場合。
- Db2 の場合、列がパーティションキー、クラスタリングキー、またはセカンダリインデックスキーの一部である場合。
RENAME TO
RENAME TO サブコマンドは、テーブルの名前を変更します。
文法
ALTER TABLE [<namespace name>.]<table name> RENAME TO <new table name>
例
RENAME TO の例は次のとおりです。
-- Rename a table "tbl" to "new_tbl" in namespace "ns"
ALTER TABLE ns.tbl RENAME TO new_tbl;
RENAME TO のステートメントオブジェクトを構築する例は次のとおりです。
// Rename a table "tbl" to "new_tbl" in namespace "ns"
AlterTableRenameToStatement statement1 =
StatementBuilder.alterTable("ns", "tbl").renameTo("new_tbl").build();
非 JDBC データベースではテーブルの名前を変更することはできません。
ALTER COLUMN SET DATA TYPE
ALTER COLUMN SET DATA TYPE サブコマンドは、テーブル内の列のデータ型を変更します。
文法
ALTER TABLE [<namespace name>.]<table name> ALTER [COLUMN] <column name> [SET DATA] TYPE data_type;
data_type: BOOLEAN | INT | BIGINT | FLOAT | DOUBLE | TEXT | BLOB | DATE | TIME | TIMESTAMP | TIMESTAMPTZ
例
ALTER COLUMN SET DATA TYPE の例は次のとおりです。
-- Change the data type of a column "col1" to BIGINT in "ns.tbl"
ALTER TABLE ns.tbl ALTER COLUMN col1 SET DATA TYPE BIGINT;
ALTER COLUMN SET DATA TYPE のステートメントオブジェクトを構築する例は次のとおりです。
// Change the data type of a column "col1" to BIGINT in "ns.tbl"
AlterTableAlterColumnStatement statement1 =
StatementBuilder.alterTable("ns", "tbl").alterColumnType("col1", DataType.BIGINT).build();
次の場合、テーブルの列のデータ型を変更することはできません。
- 列がパーティションキー、クラスタリングキー、またはセカンダリインデックスキーの一部である場合。
- テーブルが非 JDBC データベース上または SQLite 上にある場合。
- INT から BIGINT、FLOAT から DOUBLE、および任意のデータから TEXT への変換以外の変換が指定されている場合。
- Oracle の場合、INT から BIGINT 以外の変換が指定されている場合。
- Db2 および TiDB の場合、BLOB から TEXT への変換が指定されている場合。
列の型を変更する場合は、基盤となるストレージによって実行時間が大 きく異なる可能性があるため、慎重に検討する必要があります。特にデータベースが本番環境で実行されている場合は、以下の点を考慮して適切に計画を立ててください。
- リレーショナルデータベース (MySQL、Oracle など) の場合: 列の変更は、基盤となるリレーショナルデータベースに
ALTER TABLE ... ALTER COLUMNまたはALTER TABLE ... MODIFYを発行し、データベースによってはテーブルの再構築を引き起こす可能性があります。そのような場合、実行に長時間かかることがあります。
DML
SELECT
SELECT コマンドは、データベースからレコードを取得します。ScalarDB SQL は、ScalarDB の Get、パーティション Scan、およびクロスパーティション Scan 操作のいずれかを使用して、データベースからレコードを取得し、SELECT コマンドの実行プランを作成します。最良の結果を得るには、クロスパーティションスキャンの使用を避けるため、WHERE 句で主キー列を可能な限り一意に指定します。クロスパーティションスキャンを使用すると、特に非 JDBC データベースでパフォーマンスと一貫性の問題が発生する可能性があります。操作の選択については、次のルールを参照してください。前者は後者よりも優先され、より効率的です。ScalarDB データモデルは、データのモデリングとアクセスに関するベストプラクティスを理解するのにも役立ちます。
WHERE句で主キー列を完全に指定すると、SELECTコマンドは単一パーティション内の単一レコードに対してGet操作を使用します。- パーティションキーを完全に指定し、
WHERE句とORDER BY句でクラスタリングキーと順序を適切に指定すると、SELECTコマンドは単一パーティション内のレコードに対してScan操作を使用します。詳細については、パーティションスキャンとインデックススキャンの例を参照してください。 ORDER BY句を使用せずにWHERE句でequal to(=) 演算子を使用してインデックス列の値を指定すると、SELECTコマンドはインデックスScan操作を使用します。- その他の場合、
SELECTコマンドはクロスパーティションScan操作に変換されます。
任意の条件と順序でパーティション間でレコードを柔軟に取得したい場合は、クロスパーティションスキャンオプションと、フィルタリングおよび順序付けオプション付きのクロスパーティションスキャンを有効にする必要があります。現在、順序付けオプションは JDBC データベースでのみ使用できます。設定の詳細につい ては、クロスパーティションスキャン設定および ScalarDB Cluster SQL クライアント設定を参照してください。
非 JDBC データベースの場合、SERIALIZABLE 分離レベルでクロスパーティションスキャンを有効にした場合でも、トランザクションは読み取りコミットスナップショット分離 (SNAPSHOT) で実行される可能性があります。これは、より低い分離レベルです。非 JDBC データベースを使用する場合は、トランザクションの一貫性が重要でない場合にのみ、クロスパーティションスキャンを使用してください。
文法
SELECT projection [, projection] ...
FROM [<namespace name>.]<table name> [AS <alias>] [join_specification [join_specification] ...]
[WHERE and_predicates [OR and_predicates ...] | or_predicates [AND or_predicates ...]]
[GROUP BY identifier [, identifier] ...]
[HAVING having_condition]
[ORDER BY order_key [order] [, order_key [order]] ...]
[LIMIT <limit>]
[WITH operation_attributes_or_abac_read_tags]
identifier: [[<namespace name>.]<table name>.]<column name> | [alias.]<column name>
aggregate_function: <aggregate function name>(* | <column name> | <literal>)
projection: * | identifier [AS <alias>] | aggregate_function [AS <alias>]
join_specification: [INNER] JOIN [<namespace name>.]<table name> [AS <alias>] ON join_predicate [AND join_predicate] ... | {LEFT|RIGHT} [OUTER] JOIN [<namespace name>.]<table name> [AS <alias>] ON join_predicate [AND join_predicate] ...
join_predicate: identifier = identifier
and_predicates: predicate | (predicate [AND predicate ...])
or_predicates: predicate | (predicate [OR predicate ...])
predicate: identifier operator <literal> | identifier BETWEEN <literal> AND <literal> | identifier [NOT] LIKE <pattern> [ESCAPE <escape character>] | identifier IS [NOT] NULL
having_condition: having_and_predicates [OR having_and_predicates ...] | having_or_predicates [AND having_or_predicates ...]
having_and_predicates: having_predicate | (having_predicate [AND having_predicate ...])
having_or_predicates: having_predicate | (having_predicate [OR having_predicate ...])
having_predicate: (identifier | aggregate_function | <alias>) operator <literal> | (identifier | aggregate_function | <alias>) BETWEEN <literal> AND <literal> | (identifier | aggregate_function | <alias>) [NOT] LIKE <pattern> [ESCAPE <escape character>] | (identifier | aggregate_function | <alias>) IS [NOT] NULL
order_key: identifier | aggregate_function | <alias>
operator: = | <> | != | > | >= | < | <=
order: ASC | DESC
operation_attributes_or_abac_read_tags: operation_attribute_or_abac_read_tag [AND operation_attribute_or_abac_read_tag] ...
operation_attribute_or_abac_read_tag: operation_attribute | abac_read_tag
operation_attribute: <operation attribute name>=<operation attribute value>
abac_read_tag: ABAC_READ_TAG <abac read tag> FOR [POLICY] <abac policy name>
注記
JOIN 句:
[INNER] JOINおよびLEFT [OUTER] JOINの場合:join_predicateには、右側のテーブルのすべての主キー列またはセカンダリインデックス列のいずれかが含まれている必要があります。WHERE述語およびORDER BY句には、FROM句で指定されたテーブルの列のみを含めることができます。
RIGHT [OUTER] JOINの場合:- 最初の
join_specificationとして指定する必要があります。 join_predicateには、左側のテーブルのすべての主キー列またはセカンダリインデックス列が含まれている必要があります。WHERE述語およびORDER BY句には、RIGHT OUTER JOIN句で指定されたテーブルの列のみを指定できます。
- 最初の
WHERE 句:
WHERE句の任意の列に任意の述語を使用できます。WHERE句では、述語はand_predicatesの OR 形式 (論理和標準形と呼ばれます) またはor_predicatesの AND 形式 (論理積標準形と呼ばれま す) である必要があります。- 複数の述語を持つ複数の
and_predicatesまたはor_predicatesを接続する場合は、and_predicatesとor_predicatesを括弧で囲む必要があります。 - バインドマーカー (位置指定
?および名前指定:<name>) に<literal>を指定できます。リテラル文法については、リテラルセクションを参照してください。 WHERE句で暗号化された列を指定することはできません。
LIKE 述語:
<pattern>内の_は任意の1文字に一致します。<pattern>内の%は0個以上の文字の任意のシーケンスに一致します。<pattern>内の\はデフォルトでエスケープ文字として機能します。ESCAPE句を指定してエスケープ文字を変更できます。- 空のエスケープ文字
ESCAPE ''を指定してエスケープ文字を無効にすることができます。
GROUP BY 句:
- 指定された列で同じ値を持つ行をグループ化します。
SELECT句の列は、GROUP BY句に含まれるか集約関数で使用される必要があります。
HAVING 句:
- 集約関数の結果に基づいてグループをフィルタリングします。
- 集約関数を直接参照するか、エイリアスで参照できます。
- 述語は
having_and_predicatesの OR 形式(論理和標準形と呼ばれます)またはhaving_or_predicatesの AND 形式(論理積標準形と呼ばれます)である必要があります。 - 複数の述語を持つ複数の
having_and_predicatesまたはhaving_or_predicatesを接続する場合は、having_and_predicatesとhaving_or_predicatesを括弧で囲む必要があります。
集約関数:
- サポートされている関数:
COUNT、SUM、AVG、MIN、MAX。 COUNT(*)は全ての行をカウントし、COUNT(<column name>)は非 null 値をカウントします。結果の型はBIGINTです。SUMは数値型(INT、BIGINT、FLOAT、DOUBLE)を受け入れます。INTとBIGINTに対してBIGINTを返し、FLOATとDOUBLEに対してDOUBLEを返します。AVGは数値型を受け入れます。DOUBLEを返します。MINは比較可能な任意の型を受け入れます。同じ型を返します。MAXは比較可能な任意の型を受け入れます。同じ型を返します。COUNTのみが*を引数として受け入れます。
ORDER BY 句:
ORDER BY句の任意の列、集約関数、またはエイリアスにorderを指定できます。orderを省略すると、デフォルトの順序ASCが使用されます。ORDER BY句では暗号化された列を指定できません。
LIMIT 句:
- バインドマーカー (位置指定
?および名前指定:<name>) に<limit>を指定できます。
ScalarDB のデータベースからデータを取得する方法の詳細については、Get 操作および Scan 操作を参照してください。
パーティションスキャンとインデックススキャンの例
次のようなテーブルとインデックスがあるとします。
CREATE TABLE ns.tbl (
c1 INT,
c2 TEXT,
c3 FLOAT,
c4 BIGINT,
c5 BOOLEAN,
PRIMARY KEY (c1, c2, c3)
) WITH CLUSTERING ORDER BY (c2 DESC, c3 ASC);
CREATE INDEX ON ns.tbl (c4);
SELECT の例は次のとおりです。
-- With a full primary key
SELECT * FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23;
-- With a full primary key and predicates for non-primary-key columns
SELECT * FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 AND c4 < 100;
-- With a partial primary key
SELECT * FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa';
-- With a partial primary key and predicates for non-primary-key columns
SELECT * FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND (c4 < 100 OR c4 > 500);
-- With projections and a partition key and clustering-key boundaries
SELECT c1, c2, c3, c5 FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 >= 1.23 AND c3 < 4.56;
-- With projections and a partition key and clustering-key boundaries and orders and limit
SELECT c1 AS a, c2 AS b, c3 AS c, c5 FROM ns.tbl WHERE c1 = 10 AND c2 > 'aaa' AND c2 <= 'ddd' ORDER BY c2 ASC, c3 DESC LIMIT 10;
-- With an equality predicate for an indexed column
SELECT * FROM ns.tbl WHERE c4 = 100;
-- With an equality predicate for an indexed column and predicates for non-primary-key columns
SELECT * FROM ns.tbl WHERE c4 = 100 AND c5 = false;
-- With projections and an indexed column and limit
SELECT c1, c2, c3, c4 FROM ns.tbl WHERE c4 = 100 LIMIT 10;
-- With positional bind markers
SELECT * FROM ns.tbl WHERE c1 = ? AND c2 > ? AND c2 <= ? ORDER BY c2 ASC, c3 DESC LIMIT ?;
-- With operations attributes
SELECT * FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 WITH 'attribute1' = 'value1' AND 'attribute2' = 'value2';
-- With an ABAC read tag
SELECT * FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 WITH ABAC_READ_TAG 'read_tag1' FOR POLICY policy1;
-- With operations attributes and an ABAC read tag
SELECT * FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 WITH 'attribute1' = 'value1' AND 'attribute2' = 'value2' AND ABAC_READ_TAG 'read_tag1' FOR POLICY policy1;
SELECT のステートメントオブジェクトを構築する例 は次のとおりです。
// With a full primary key
SelectStatement statement1 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.and(Predicate.column("c4").isLessThan(Value.of(100)))
.build();
// With a full primary key and predicates for non-primary-key columns
SelectStatement statement1 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c4").isEqualTo(Value.of(1.23F)))
.and(Predicate.column("c4").isLessThan(Value.of(100)))
.build();
// With a partial primary key
SelectStatement statement2 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.build();
// With a partial primary key and predicates for non-primary-key columns
SelectStatement statement2 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(
AndPredicateList.predicate(Predicate.column("c4").isLessThan(Value.of(100)))
.and(Predicate.column("c4").isGreaterThan(Value.of(500)))
.build())
.build();
// With projections and a partition key and clustering-key boundaries
SelectStatement statement3 =
StatementBuilder.select("c1", "c2", "c3", "c5")
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isGreaterThanOrEqualTo(Value.of(1.23F)))
.and(Predicate.column("c3").isLessThan(Value.of(4.56F)))
.build();
// With projections and a partition key and clustering key boundaries and orders and limit
SelectStatement statement4 =
StatementBuilder.select(
Projection.column("c1").as("a"),
Projection.column("c2").as("b"),
Projection.column("c3").as("c"),
Projection.column("c5").as("d"))
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isGreaterThan(Value.of("aaa")))
.and(Predicate.column("c2").isLessThanOrEqualTo(Value.of("ddd")))
.orderBy(Ordering.column("c2").asc(), Ordering.column("c3").desc())
.limit(10)
.build();
// With an equality predicate for an indexed column
SelectStatement statement5 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c4").isEqualTo(Value.of(100)))
.build();
// With an equality predicate for an indexed column and predicates for non-primary-key columns
SelectStatement statement5 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c4").isEqualTo(Value.of(100)))
.and(Predicate.column("c5").isEqualTo(Value.of(false)))
.build();
// With projections and an indexed column and limit
SelectStatement statement6 =
StatementBuilder.select("c1", "c2", "c3", "c4")
.from("ns", "tbl")
.where(Predicate.column("c4").isEqualTo(Value.of(100)))
.limit(10)
.build();
// With positional bind markers
SelectStatement statement7 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(BindMarker.positional()))
.and(Predicate.column("c2").isGreaterThan(BindMarker.positional()))
.and(Predicate.column("c2").isLessThanOrEqualTo(BindMarker.positional()))
.orderBy(Ordering.column("c2").asc(), Ordering.column("c3").desc())
.limit(BindMarker.positional())
.build();
// With operations attributes
SelectStatement statement8 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.withAttribute("attribute1", "value1")
.withAttribute("attribute2", "value2")
.build();
// With an ABAC read tag
SelectStatement statement9 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.withAbacReadTag("read_tag1", "policy1")
.build();
// With operations attributes and an ABAC read tag
SelectStatement statement10 =
StatementBuilder.select()
.from("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.withAttribute("attribute1", "value1")
.withAttribute("attribute2", "value2")
.withAbacReadTag("read_tag1", "policy1")
.build();
JOIN を使用した SELECT の例は次のとおりです。
-- For INNER JOIN and LEFT OUTER JOIN:
SELECT * FROM tbl1 as t1
INNER JOIN tbl2 as t2 on t1.col1=t2.id1 and t1.col2=t2.id2 -- This part must have all primary key columns or a secondary index column of `tbl2`.
WHERE t1.pkey=1 -- Only columns of `tbl1` can be specified here.
ORDER BY t1.ckey DESC; -- Only columns of `tbl1` can be specified here.
SELECT * FROM tbl1 as t1
INNER JOIN tbl2 as t2 on t1.col1=t2.id -- This part must have all primary key columns or a secondary index column of `tbl2`.
LEFT OUTER JOIN tbl3 as t3 on t1.col2=t3.id -- This part must have all primary key columns or a secondary index column of `tbl3`.
WHERE t1.pkey=1 -- Only columns of `tbl1` can be specified here.
ORDER BY t1.ckey DESC; -- Only columns of `tbl1` can be specified here.
-- For RIGHT OUTER JOIN:
SELECT * FROM tbl1 as t1
RIGHT OUTER JOIN tbl2 as t2 on t1.id=t2.col -- Acceptable as the first join. And this part must have all primary key columns or a secondary index column of `tbl1`.
LEFT OUTER JOIN tbl3 as t3 on t1.col2=t3.id
WHERE t2.pkey=1 -- Only columns of `tbl2` can be specified here.
ORDER BY t2.ckey DESC; -- Only columns of `tbl2` can be specified here.
SELECT * FROM tbl1 as t1
RIGHT OUTER JOIN tbl2 as t2 on t1.id1=t2.col1 and t1.id2=t2.col2 -- This part must have all primary key columns or a secondary index column of `tbl1`.
WHERE t2.pkey=1 -- Only columns of `tbl2` can be specified here.
ORDER BY t2.ckey DESC; -- Only columns of `tbl2` can be specified here.
JOIN を使用して SELECT のステートメントオブジェクトを構築する例は次のとおりです。
// For INNER JOIN and LEFT OUTER JOIN:
SelectStatement statement1 =
StatementBuilder.select()
.from("tbl1", "t1")
.innerJoin("tbl2", "t2")
.on(JoinPredicate.column("t1", "col1").isEqualTo("t2", "id1"))
.and(JoinPredicate.column("t1", "col2").isEqualTo("t2", "id2")) // This part must have all primary key columns or a secondary index column of `tbl2`.
.where(Predicate.column("t1", "pkey").isEqualTo(Value.of(1))) // Only columns of `tbl1` can be specified here.
.orderBy(Ordering.column("t1", "ckey").desc()) // Only columns of `tbl1` can be specified here.
.build();
SelectStatement statement2 =
StatementBuilder.select()
.from("tbl1", "t1")
.innerJoin("tbl2", "t2")
.on(JoinPredicate.column("t1", "col1").isEqualTo("t2", "id")) // This part must have all primary key columns or a secondary index column of `tbl2`.
.leftOuterJoin("tbl3", "t3")
.on(JoinPredicate.column("t1", "col2").isEqualTo("t3", "id")) // This part must have all primary key columns or a secondary index column of `tbl3`.
.where(Predicate.column("t1", "pkey").isEqualTo(Value.of(1))) // Only columns of `tbl1` can be specified here.
.orderBy(Ordering.column("t1", "ckey").desc()) // Only columns of `tbl1` can be specified here.
.build();
// For RIGHT OUTER JOIN:
SelectStatement statement3 =
StatementBuilder.select()
.from("tbl1", "t1")
.rightOuterJoin("tbl2", "t2")
.on(JoinPredicate.column("t1", "id").isEqualTo("t2", "col")) // Acceptable as the first join. And this part must have all primary key columns or a secondary index column of `tbl1`.
.leftOuterJoin("tbl3", "t3")
.on(JoinPredicate.column("t1", "col2").isEqualTo("t3", "id"))
.where(Predicate.column("t2", "pkey").isEqualTo(Value.of(1))) // Only columns of `tbl2` can be specified here.
.orderBy(Ordering.column("t2", "ckey").desc()) // Only columns of `tbl2` can be specified here.
.build();
SelectStatement statement4 =
StatementBuilder.select()
.from("tbl1", "t1")
.rightOuterJoin("tbl2", "t2")
.on(JoinPredicate.column("t1", "id1").isEqualTo("t2", "col1"))
.and(JoinPredicate.column("t1", "id2").isEqualTo("t2", "col2")) // This part must have all primary key columns or a secondary index column of `tbl1`.
.where(Predicate.column("t2", "pkey").isEqualTo(Value.of(1))) // Only columns of `tbl2` can be specified here.
.orderBy(Ordering.column("t2", "ckey").desc()) // Only columns of `tbl2` can be specified here.
.build();
クロスパーティションスキャンの例
たとえば、次のテーブルがあるとします。
CREATE TABLE ns.user (
id INT,
name TEXT,
age INT,
height FLOAT,
PRIMARY KEY (id)
)
クロスパーティションスキャンを使用した SELECT の例は次のとおりです。
-- Without the WHERE clause to retrieve all the records of a table
SELECT * FROM ns.user;
-- Without the WHERE clause and with projections and a limit
SELECT id, name FROM ns.user LIMIT 10;
-- With AND predicates for non-primary-key columns
SELECT * FROM ns.user WHERE age > 10 AND height > 140;
-- With OR predicates for non-primary key columns
SELECT * FROM ns.user WHERE age > 10 OR height > 140;
-- With OR-wise of AND predicates
SELECT * FROM ns.user WHERE (age > 10 AND height > 150) OR (age > 15 AND height > 145);
-- With AND-wise of OR predicates
SELECT * FROM ns.user WHERE (age < 10 OR age > 65) AND (height < 145 OR height > 175);
-- With LIKE predicates
SELECT * FROM ns.user WHERE name LIKE 'A%' OR name NOT LIKE 'B_b';
-- With LIKE predicates with an escape character
SELECT * FROM ns.user WHERE name LIKE '+%Alice' ESCAPE '+';
-- With IS NULL predicates
SELECT * FROM ns.user WHERE name IS NOT NULL AND age IS NULL;
-- With projections
SELECT name, age, height FROM ns.user WHERE (age < 10 OR age > 65) AND age <> 0;
-- With limit
SELECT name, age, height FROM ns.user WHERE age < 10 OR age > 65 LIMIT 10;
-- With orderings
SELECT * FROM ns.user WHERE age < 10 ORDER BY height DESC;
-- With orderings without the WHERE clause
SELECT * FROM ns.user ORDER BY height;
-- With positional bind markers
SELECT * FROM ns.user WHERE age < ? ORDER BY age ASC, height DESC LIMIT ?;
JOIN 句を使用する例については、パーティションスキャンとインデックススキャンの例を参照してください。
SELECT のステートメントオブジェクトを構築する例は次のとおりです。
// Without the WHERE clause to retrieve all the records of a table
SelectStatement statement1 = StatementBuilder.select().from("ns", "user").build();
// Without the WHERE clause and with projections and a limit
SelectStatement statement2 =
StatementBuilder.select("id", "name").from("ns", "user").limit(10).build();
// With AND predicates for non-primary-key columns
SelectStatement statement2 =
StatementBuilder.select()
.from("ns", "user")
.where(Predicate.column("age").isGreaterThan(Value.of(10)))
.and(Predicate.column("height").isGreaterThan(Value.of(140.0F)))
.build();
// With OR predicates for non-primary key columns
SelectStatement statement3 =
StatementBuilder.select()
.from("ns", "user")
.where(Predicate.column("age").isGreaterThan(Value.of(10)))
.or(Predicate.column("height").isGreaterThan(Value.of(140.0F)))
.build();
// With OR-wise of AND predicates
SelectStatement statement4 =
StatementBuilder.select()
.from("ns", "user")
.where(
AndPredicateList.predicate(Predicate.column("age").isGreaterThan(Value.of(10)))
.and(Predicate.column("height").isGreaterThan(Value.of(140.0F)))
.build())
.or(
AndPredicateList.predicate(Predicate.column("age").isGreaterThan(Value.of(15)))
.and(Predicate.column("height").isGreaterThan(Value.of(145.0F)))
.build())
.build();
// With AND-wise of OR predicates
SelectStatement statement5 =
StatementBuilder.select()
.from("ns", "user")
.where(
OrPredicateList.predicate(Predicate.column("age").isLessThan(Value.of(10)))
.or(Predicate.column("age").isGreaterThan(Value.of(65)))
.build())
.and(
OrPredicateList.predicate(Predicate.column("height").isLessThan(Value.of(145.0F)))
.or(Predicate.column("height").isGreaterThan(Value.of(175.0F)))
.build())
.build();
// With LIKE predicates
SelectStatement statement6 =
StatementBuilder.select()
.from("ns", "user")
.where(Predicate.column("name").isLike(Value.of("A%")))
.or(Predicate.column("name").isNotLike(Value.of("B_b")))
.build();
// With LIKE predicates with an escape character
SelectStatement statement7 =
StatementBuilder.select()
.from("ns", "user")
.where(Predicate.column("name").isLike(Value.of("+%Alice"), Value.of("+")))
.build();
// With IS NULL predicates
SelectStatement statement8 =
StatementBuilder.select()
.from("ns", "user")
.where(Predicate.column("name").isNotNull())
.and(Predicate.column("age").isNull())
.build();
// With projections
SelectStatement statement9 =
StatementBuilder.select("name", "age", "height")
.from("ns", "user")
.where(
OrPredicateList.predicate(Predicate.column("age").isLessThan(Value.of(10)))
.or(Predicate.column("age").isGreaterThan(Value.of(65)))
.build())
.and(Predicate.column("height").isNotEqualTo(Value.of(0)))
.build();
// With limit
SelectStatement statement10 =
StatementBuilder.select("name", "age", "height")
.from("ns", "user")
.where(Predicate.column("age").isLessThan(Value.of(10)))
.or(Predicate.column("age").isGreaterThan(Value.of(65)))
.limit(10)
.build();
// With orderings
SelectStatement statement11 =
StatementBuilder.select()
.from("ns", "user")
.where(Predicate.column("age").isLessThan(Value.of(10)))
.orderBy(Ordering.column("height").desc())
.build();
// With orderings without the WHERE clause
SelectStatement statement12 =
StatementBuilder.select()
.from("ns", "user")
.orderBy(Ordering.column("height").desc())
.build();
// With positional bind markers
SelectStatement statement13 =
StatementBuilder.select()
.from("ns", "user")
.where(Predicate.column("age").isLessThan(BindMarker.positional()))
.orderBy(Ordering.column("age").asc(), Ordering.column("height").desc())
.limit(BindMarker.positional())
.build();
JOIN 句を使用する例については、パーティションスキャンとインデックススキャンの例を参照してください。
集約クエリの例
次のようなテーブルがあるとします。
CREATE TABLE ns.user (
id INT,
name TEXT,
age INT,
height FLOAT,
PRIMARY KEY (id)
);
集約クエリの例は次のとおりです。
-- 集約関数を使用
SELECT COUNT(*) FROM ns.user;
-- GROUP BY を使用
SELECT age, COUNT(*) FROM ns.user GROUP BY age;
-- 複数の集約関数を使用
SELECT age, COUNT(height), SUM(height), AVG(height), MIN(height), MAX(height) FROM ns.user GROUP BY age;
-- 集約関数のエイリアスと HAVING を使用
SELECT age, COUNT(*) AS cnt FROM ns.user GROUP BY age HAVING cnt > 1;
-- HAVING で集約関数を直接使用
SELECT age, COUNT(*) FROM ns.user GROUP BY age HAVING COUNT(*) > 1;
-- GROUP BY、WHERE、ORDER BY でエイリアスを使用、および LIMIT を使用
SELECT age, SUM(height) AS total_height FROM ns.user WHERE name LIKE 'A%' GROUP BY age ORDER BY total_height DESC LIMIT 10;
集約クエリのステートメントオブジェクトを構築する例は次のとおりです。
// 集約関数を使用
SelectStatement statement1 =
StatementBuilder.select(
Projection.function(
FunctionRef.of("COUNT", ImmutableList.of(FunctionRef.StarFunctionArg.create()))))
.from("ns", "user")
.build();
// GROUP BY を使用
SelectStatement statement2 =
StatementBuilder.select(
Projection.column("age"),
Projection.function(
FunctionRef.of("COUNT", ImmutableList.of(FunctionRef.StarFunctionArg.create()))))
.from("ns", "user")
.groupBy(ColumnRef.of("age"))
.build();
// 複数の集約関数を使用
SelectStatement statement3 =
StatementBuilder.select(
Projection.column("age"),
Projection.function(
FunctionRef.of("COUNT", ImmutableList.of(FunctionRef.ColumnFunctionArg.create(ColumnRef.of("height"))))),
Projection.function(
FunctionRef.of("SUM", ImmutableList.of(FunctionRef.ColumnFunctionArg.create(ColumnRef.of("height"))))),
Projection.function(
FunctionRef.of("AVG", ImmutableList.of(FunctionRef.ColumnFunctionArg.create(ColumnRef.of("height"))))),
Projection.function(
FunctionRef.of("MIN", ImmutableList.of(FunctionRef.ColumnFunctionArg.create(ColumnRef.of("height"))))),
Projection.function(
FunctionRef.of("MAX", ImmutableList.of(FunctionRef.ColumnFunctionArg.create(ColumnRef.of("height"))))))
.from("ns", "user")
.groupBy(ColumnRef.of("age"))
.build();
// 集約関数のエイリアスと HAVING を使用
SelectStatement statement4 =
StatementBuilder.select(
Projection.column("age"),
Projection.function(
FunctionRef.of("COUNT", ImmutableList.of(FunctionRef.StarFunctionArg.create()))).as("cnt"))
.from("ns", "user")
.groupBy(ColumnRef.of("age"))
.having(HavingPredicate.column("cnt").isGreaterThan(Value.of(1L)))
.build();
// HAVING で集約関数を直接使用
SelectStatement statement5 =
StatementBuilder.select(Projection.column("age"), Projection.function(FunctionRef.of("COUNT", ImmutableList.of(FunctionRef.StarFunctionArg.create()))))
.from("ns", "user")
.groupBy(ColumnRef.of("age"))
.having(HavingPredicate.function(FunctionRef.of("COUNT", ImmutableList.of(FunctionRef.StarFunctionArg.create()))).isGreaterThan(Value.of(1L)))
.build();
// GROUP BY、WHERE、ORDER BY でエイリアスを使用、および LIMIT を使用
SelectStatement statement6 =
StatementBuilder.select(
Projection.column("age"),
Projection.function(
FunctionRef.of("SUM", ImmutableList.of(FunctionRef.ColumnFunctionArg.create(ColumnRef.of("height"))))).as("total_height"))
.from("ns", "user")
.where(Predicate.column("name").isLike(Value.of("A%")))
.groupBy(ColumnRef.of("age"))
.orderBy(Ordering.column("total_height").desc())
.limit(10)
.build();
INSERT
INSERT コマンドは、データベースに新しいレコードを挿入します。対象レコードのいずれかがすでに存在する場合、トランザクション競合エラーがスローされます。
このコマンドは次の列を返します:
updateCount:INT- 挿入されたレコードの数
文法
INSERT INTO [<namespace name>.]<table name> [(<column name> [, <column name>] ...)]
VALUES (<literal> [, <literal>] ...) [, (<literal> [, <literal>] ...)] ...
[WITH operation_attributes_or_abac_read_tags_or_abac_write_tags]
operation_attributes_or_abac_read_tags_or_abac_write_tags: operation_attribute_or_abac_read_tag_or_abac_write_tag [AND operation_attribute_or_abac_read_tag_or_abac_write_tag] ...
operation_attribute_or_abac_read_tag_or_abac_write_tag: operation_attribute | abac_read_tag | abac_write_tag
operation_attribute: <operation attribute name>=<operation attribute value>
abac_read_tag: ABAC_READ_TAG <abac read tag> FOR [POLICY] <abac policy name>
abac_write_tag: ABAC_WRITE_TAG <abac write tag> FOR [POLICY] <abac policy name>
INSERTでは完全な主キーを指定する必要があります。- バインドマーカー (位置
?および名前:<name>) に<literal>を指定できます。リテラル文法については、リテラルセクションを参照してください。
例
INSERT の例は次のとおりです。
-- Insert a record without specifying column names
INSERT INTO ns.tbl VALUES (10, 'aaa', 1.23, 100, true);
-- Insert a record with column names
INSERT INTO ns.tbl (c1, c2, c3, c4) VALUES (10, 'aaa', 1.23, 100);
-- With positional bind markers
INSERT INTO tbl VALUES (?, ?, ?, ?, ?);
-- Insert multiple records
INSERT INTO ns.tbl (c1, c2, c3, c4) VALUES (10, 'aaa', 1.23, 100), (20, 'bbb', 4.56, 200);
INSERT のステートメントオブジェクトを構築する例は次のとおりです。
// Insert a record without specifying column names.
InsertStatement statement1 = StatementBuilder.insertInto("ns", "tbl")
.values(Value.ofInt(10), Value.ofText("aaa"), Value.of(1.23F), Value.of(100L), Value.of(true))
.build();
// Insert a record with column names.
InsertStatement statement2 = StatementBuilder.insertInto("ns", "tbl")
.columns("c1", "c2", "c3", "c4", "c5")
.values(Value.ofInt(10), Value.ofText("aaa"), Value.of(1.23F), Value.of(100L), Value.of(true))
.build();
// With positional bind markers
InsertStatement statement3 =
StatementBuilder.insertInto("tbl")
.columns("c1", "c2", "c3", "c4", "c5")
.values(
BindMarker.positional(),
BindMarker.positional(),
BindMarker.positional(),
BindMarker.positional(),
BindMarker.positional())
.build();
// Insert multiple records.
InsertStatement statement4 = StatementBuilder.insertInto("ns", "tbl")
.columns("c1", "c2", "c3", "c4", "c5")
.values(Value.ofInt(10), Value.ofText("aaa"), Value.of(1.23F), Value.of(100L), Value.of(true))
.values(Value.ofInt(20), Value.ofText("bbb"), Value.of(2.46F), Value.of(200L), Value.of(false))
.build();
UPSERT
UPSERT コマンドは、データベースに新しいレコードが存在しない場合はそれを挿入し、すでに存在する場合はターゲットレコードを更新します。
このコマンドは次の列を返します:
updateCount:INT- 挿入または更新されたレコードの数
文法
UPSERT INTO [<namespace name>.]<table name> [(<column name> [, <column name>] ...)]
VALUES (<literal> [, <literal>] ...) [, (<literal> [, <literal>] ...)] ...
[WITH operation_attributes]
operation_attributes: <operation attribute name>=<operation attribute value> [AND <operation attribute name>=<operation attribute value>] ...
INSERTでは完全な主キーを指定する必要があります。- バインドマーカー (位置
?および名前:<name>) に<literal>を指定できます。リテラル文法については、リテラルセクションを参照してください。
例
UPSERT の例は次のとおりです。
-- Upsert a record without specifying column names.
UPSERT INTO ns.tbl VALUES (10, 'aaa', 1.23, 100, true);
-- Upsert a record with column names.
UPSERT INTO ns.tbl (c1, c2, c3, c4) VALUES (10, 'aaa', 1.23, 100);
-- With positional bind markers
UPSERT INTO tbl VALUES (?, ?, ?, ?, ?);
-- Upsert multiple records.
UPSERT INTO ns.tbl (c1, c2, c3, c4) VALUES (10, 'aaa', 1.23, 100), (20, 'bbb', 4.56, 200);
-- With operations attributes
UPSERT INTO ns.tbl VALUES (10, 'aaa', 1.23, 100, true) WITH 'attribute1' = 'value1' AND 'attribute2' = 'value2';
-- With an ABAC read tag and an ABAC write tag
UPSERT INTO ns.tbl VALUES (10, 'aaa', 1.23, 100, true) WITH ABAC_READ_TAG 'read_tag1' FOR POLICY policy1 AND ABAC_WRITE_TAG 'write_tag1' FOR POLICY policy1;
-- With operations attributes and ABAC read and write tags
UPSERT INTO ns.tbl VALUES (10, 'aaa', 1.23, 100, true) WITH 'attribute1' = 'value1' AND 'attribute2' = 'value2' AND ABAC_READ_TAG 'read_tag1' FOR POLICY policy1 AND ABAC_WRITE_TAG 'write_tag1' FOR POLICY policy1;
UPSERT のステートメン トオブジェクトを構築する例は次のとおりです。
// Upsert a record without specifying column names.
UpsertStatement statement1 =
StatementBuilder.upsertInto("ns", "tbl")
.values(
Value.ofInt(10),
Value.ofText("aaa"),
Value.of(1.23F),
Value.of(100L),
Value.of(true))
.build();
// Upsert a record with column names.
UpsertStatement statement2 =
StatementBuilder.upsertInto("ns", "tbl")
.columns("c1", "c2", "c3", "c4", "c5")
.values(
Value.ofInt(10),
Value.ofText("aaa"),
Value.of(1.23F),
Value.of(100L),
Value.of(true))
.build();
// With positional bind markers
UpsertStatement statement3 =
StatementBuilder.upsertInto("tbl")
.columns("c1", "c2", "c3", "c4", "c5")
.values(
BindMarker.positional(),
BindMarker.positional(),
BindMarker.positional(),
BindMarker.positional(),
BindMarker.positional())
.build();
// Upsert multiple records.
UpsertStatement statement4 =
StatementBuilder.upsertInto("ns", "tbl")
.columns("c1", "c2", "c3", "c4", "c5")
.values(
Value.ofInt(10),
Value.ofText("aaa"),
Value.of(1.23F),
Value.of(100L),
Value.of(true))
.values(
Value.ofInt(20),
Value.ofText("bbb"),
Value.of(2.46F),
Value.of(200L),
Value.of(false))
.build();
// With operations attributes
UpsertStatement statement5 =
StatementBuilder.upsertInto("ns", "tbl")
.values(
Value.ofInt(10),
Value.ofText("aaa"),
Value.of(1.23F),
Value.of(100L),
Value.of(true))
.withAttribute("attribute1", "value1")
.withAttribute("attribute2", "value2")
.build();
// With an ABAC read tag and an ABAC write tag
UpsertStatement statement6 =
StatementBuilder.upsertInto("ns", "tbl")
.values(
Value.ofInt(10),
Value.ofText("aaa"),
Value.of(1.23F),
Value.of(100L),
Value.of(true))
.withAbacReadTag("read_tag1", "policy1")
.withAbacWriteTag("write_tag1", "policy1")
.build();
// With operations attributes and ABAC read and write tags
UpsertStatement statement7 =
StatementBuilder.upsertInto("ns", "tbl")
.values(
Value.ofInt(10),
Value.ofText("aaa"),
Value.of(1.23F),
Value.of(100L),
Value.of(true))
.withAttribute("attribute1", "value1")
.withAttribute("attribute2", "value2")
.withAbacReadTag("read_tag1", "policy1")
.withAbacWriteTag("write_tag1", "policy1")
.build();
UPDATE
UPDATE コマンドは、データベース内の既存のレコードを更新します。WHERE 句に任意の条件を指定してレコードをフィルタリングできます。ただし、特に非 JDBC データベースでは、クロスパーティション操作によってパフォーマンスと一貫性の問題が発生する可能性があるため、クロスパーティション操作を回避するには、主キーを可能な限り一意に指定することをお勧めします。ScalarDB SQL は、Get または Scan 操作を使用してターゲットレコードを識別する UPDATE コマンドの実行プランを作成するため、レコードの選択にも同じルールが適用されます。クロスパーティション操作を引き起こす WHERE 句の種類を理解し、そのような操作を回避するには、SELECT を参照してください。
WHERE 句を指定せずにパーティション全体のすべてのレコードを更新する場合は、クロスパーティションスキャンオプションを有効にする必要があります。また、WHERE 句で任意の条件を使用してパーティション全体のレコードを柔軟に更新する場合は、フィルタリングオプション付きのクロスパーティションスキャンを有効にする必要があります。設定の詳細については、クロスパーティションスキャン設定および ScalarDB Cluster SQL クライアント設定を参照してください。
非 JDBC データベースの場合、SERIALIZABLE 分離レベルでクロスパーティションスキャンを有効にした場合でも、トランザクションは読み取りコミットスナップショット分離 (SNAPSHOT) で実行される可能性があります。これは、より低い分離レベルです。非 JDBC データベースを使用する場合は、トランザクションの一貫性が重要でない場合にのみ、クロスパーティションスキャンを使用してください。
このコマンドは次の列を返します:
updateCount:INT- 更新されたレコードの数
文法
UPDATE [<namespace name>.]<table name> [AS <alias>]
SET <column identifier> = <literal> [, <column identifier> = <literal>] ...
[WHERE and_predicates [OR and_predicates ...] | or_predicates [AND or_predicates ...]]
[WITH operation_attributes_or_abac_read_tags_or_abac_write_tags]
identifier: [[<namespace name>.]<table name>.]<column name> | [alias.]<column name>
and_predicates: predicate | (predicate [AND predicate ...])
or_predicates: predicate | (predicate [OR predicate ...])
predicate: <identifier> operator <literal> | <identifier> BETWEEN <literal> AND <literal> | <identifier> [NOT] LIKE <pattern> [ESCAPE <escape character>] | <identifier> IS [NOT] NULL
operator: = | <> | != | > | >= | < | <=
operation_attributes_or_abac_read_tags_or_abac_write_tags: operation_attribute_or_abac_read_tag_or_abac_write_tag [AND operation_attribute_or_abac_read_tag_or_abac_write_tag] ...
operation_attribute_or_abac_read_tag_or_abac_write_tag: operation_attribute | abac_read_tag | abac_write_tag
operation_attribute: <operation attribute name>=<operation attribute value>
abac_read_tag: ABAC_READ_TAG <abac read tag> FOR [POLICY] <abac policy name>
abac_write_tag: ABAC_WRITE_TAG <abac write tag> FOR [POLICY] <abac policy name>
注記
WHERE 句:
WHERE句の任意の列に任意の述語を使用できます。WHERE句では、述語はand_predicatesの OR 形式 (論理和標準形と呼ばれます) またはor_predicatesの AND 形式 (論理積標準形と呼ばれます) である必要があります。- 複数の述語を持つ複数の
and_predicatesまたはor_predicatesを接続する場合は、and_predicatesとor_predicatesを括弧で囲む必要があります。 - バインドマーカー (位置
?および名前:<name>) に<literal>を指定できます。リテラル文法については、リテラルセクションを参照してください。 WHERE句で暗号化された列を指定することはできません。
LIKE 述語:
<pattern>内の_は任意の1文字に一致します。<pattern>内の%は0個以上の文字の任意のシーケンスに一致します。<pattern>内の\はデフォルトでエスケープ文字として機能します。ESCAPE句を指定してエスケープ文字を変更できます。- 空のエスケープ文字
ESCAPE ''を指定してエスケープ文字を無効にすることができます。
主キーを指定した例
たとえば、次のテーブルがあるとします。
CREATE TABLE ns.tbl (
c1 INT,
c2 TEXT,
c3 FLOAT,
c4 BIGINT,
c5 BOOLEAN,
PRIMARY KEY (c1, c2, c3)
) WITH CLUSTERING ORDER BY (c2 DESC, c3 ASC);
完全な主キーを指定した UPDATE の例は次のとおりです。
-- Update a record
UPDATE ns.tbl SET c4 = 200, c5 = false WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23;
-- With positional bind markers
UPDATE ns.tbl SET c4 = ?, c5 = ? WHERE c1 = ? AND c2 = ? AND c3 = ?;
-- With operations attributes
UPDATE ns.tbl SET c4 = 200, c5 = false WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 WITH 'attribute1' = 'value1' AND 'attribute2' = 'value2';
-- With an ABAC read tag and an ABAC write tag
UPDATE ns.tbl SET c4 = 200, c5 = false WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 WITH ABAC_READ_TAG 'read_tag1' FOR POLICY policy1 AND ABAC_WRITE_TAG 'write_tag1' FOR POLICY policy1;
-- With operations attributes and ABAC read and write tags
UPDATE ns.tbl SET c4 = 200, c5 = false WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 WITH 'attribute1' = 'value1' AND 'attribute2' = 'value2' AND ABAC_READ_TAG 'read_tag1' FOR POLICY policy1 AND ABAC_WRITE_TAG 'write_tag1' FOR POLICY policy1;
UPDATE のステートメントオブジェクトを構築する例は次のとおりです。
// Update a record
UpdateStatement statement1 =
StatementBuilder.update("ns", "tbl")
.set(
Assignment.column("c4").value(Value.of(200L)),
Assignment.column("c5").value(Value.of(false)))
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.build();
// With positional bind markers
UpdateStatement statement2 =
StatementBuilder.update("tbl")
.set(
Assignment.column("c4").value(BindMarker.positional()),
Assignment.column("c5").value(BindMarker.positional()))
.where(Predicate.column("c1").isEqualTo(BindMarker.positional()))
.and(Predicate.column("c2").isEqualTo(BindMarker.positional()))
.and(Predicate.column("c3").isEqualTo(BindMarker.positional()))
.build();
// With operations attributes
UpdateStatement statement3 =
StatementBuilder.update("ns", "tbl")
.set(
Assignment.column("c4").value(Value.of(200L)),
Assignment.column("c5").value(Value.of(false)))
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.withAttribute("attribute1", "value1")
.withAttribute("attribute2", "value2")
.build();
// With an ABAC read tag and an ABAC write tag
UpdateStatement statement4 =
StatementBuilder.update("ns", "tbl")
.set(
Assignment.column("c4").value(Value.of(200L)),
Assignment.column("c5").value(Value.of(false)))
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.withAbacReadTag("read_tag1", "policy1")
.withAbacWriteTag("write_tag1", "policy1")
.build();
// With operations attributes and ABAC read and write tags
UpdateStatement statement5 =
StatementBuilder.update("ns", "tbl")
.set(
Assignment.column("c4").value(Value.of(200L)),
Assignment.column("c5").value(Value.of(false)))
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.withAttribute("attribute1", "value1")
.withAttribute("attribute2", "value2")
.withAbacReadTag("read_tag1", "policy1")
.withAbacWriteTag("write_tag1", "policy1")
.build();
完全な主キーが指定されていない例
たとえば、次のテーブルがあるとします。
CREATE TABLE ns.user (
id INT,
name TEXT,
age INT,
height FLOAT,
PRIMARY KEY (id)
)
完全な主キーを指定しない UPDATE の例は次のとおりです。
-- Without the WHERE clause to update all the records of a table
UPDATE ns.user SET age = 31;
-- With AND predicates for non-primary key columns
UPDATE ns.user SET age = 31 WHERE age > 10 AND height > 140;
-- With OR predicates for non-primary key columns
UPDATE ns.user SET age = 31 WHERE age > 10 OR height > 140;
-- With OR-wise of AND predicates
UPDATE ns.user SET age = 31 WHERE (age > 10 AND height > 150) OR (age > 15 AND height > 145);
-- With AND-wise of OR predicates
UPDATE ns.user SET age = 31 WHERE (age < 10 OR age > 65) AND (height < 145 OR height > 175);
-- With LIKE predicates
UPDATE ns.user SET age = 31 WHERE name LIKE 'A%' OR name NOT LIKE 'B_b';
-- With LIKE predicates with an escape character
UPDATE ns.user SET age = 31 WHERE name LIKE '+%Alice' ESCAPE '+';
-- With IS NULL predicates
UPDATE ns.user SET age = 31 WHERE name IS NOT NULL AND age IS NULL;
-- With positional bind markers
UPDATE ns.user SET age = ? WHERE age < ?;
UPDATE のステートメントオブジェクトを構築する例は次のとおりです。
// Without the WHERE clause to update all the records of a table
UpdateStatement statement1 =
StatementBuilder.update("ns", "user")
.set(Assignment.column("age").value(Value.of(30)))
.build();
// With AND predicates for non-primary key columns
UpdateStatement statement2 =
StatementBuilder.update("ns", "user")
.set(Assignment.column("age").value(Value.of(30)))
.where(Predicate.column("age").isGreaterThan(Value.of(10)))
.and(Predicate.column("height").isGreaterThan(Value.of(140.0F)))
.build();
// With OR predicates for non-primary key columns
UpdateStatement statement3 =
StatementBuilder.update("ns", "user")
.set(Assignment.column("age").value(Value.of(30)))
.where(Predicate.column("age").isGreaterThan(Value.of(10)))
.or(Predicate.column("height").isGreaterThan(Value.of(140.0F)))
.build();
// With OR-wise of AND predicates
UpdateStatement statement4 =
StatementBuilder.update("ns", "user")
.set(Assignment.column("age").value(Value.of(30)))
.where(
AndPredicateList.predicate(Predicate.column("age").isGreaterThan(Value.of(10)))
.and(Predicate.column("height").isGreaterThan(Value.of(140.0F)))
.build())
.or(
AndPredicateList.predicate(Predicate.column("age").isGreaterThan(Value.of(15)))
.and(Predicate.column("height").isGreaterThan(Value.of(145.0F)))
.build())
.build();
// With AND-wise of OR predicates
UpdateStatement statement5 =
StatementBuilder.update("ns", "user")
.set(Assignment.column("age").value(Value.of(30)))
.where(
OrPredicateList.predicate(Predicate.column("age").isLessThan(Value.of(10)))
.or(Predicate.column("age").isGreaterThan(Value.of(65)))
.build())
.and(
OrPredicateList.predicate(Predicate.column("height").isLessThan(Value.of(145.0F)))
.or(Predicate.column("height").isGreaterThan(Value.of(175.0F)))
.build())
.build();
// With LIKE predicates
UpdateStatement statement6 =
StatementBuilder.update("ns", "user")
.set(Assignment.column("age").value(Value.of(30)))
.where(Predicate.column("name").isLike(Value.of("A%")))
.or(Predicate.column("name").isNotLike(Value.of("B_b")))
.build();
// With LIKE predicates with an escape character
UpdateStatement statement7 =
StatementBuilder.update("ns", "user")
.set(Assignment.column("age").value(Value.of(30)))
.where(Predicate.column("name").isLike(Value.of("+%Alice"), Value.of("+")))
.build();
// With IS NULL predicates
UpdateStatement statement8 =
StatementBuilder.update("ns", "user")
.set(Assignment.column("age").value(Value.of(30)))
.where(Predicate.column("name").isNotNull())
.and(Predicate.column("age").isNull())
.build();
// With positional bind markers
UpdateStatement statement9 =
StatementBuilder.update("ns", "user")
.set(Assignment.column("age").value(BindMarker.positional()))
.where(Predicate.column("age").isLessThan(BindMarker.positional()))
.build();
DELETE
DELETE コマンドは、データベース内のレコードを削除します。WHERE 句に任意の条件を指定してレコードをフィルターできます。ただし、特に非 JDBC データベースでは、クロスパーティション操作によってパフォーマンスと一貫性の問題が発生する可能性があるため、クロスパーティション操作を回避するには、可能な限り主キーを一意に指定することをお勧めします。ScalarDB SQL は、ターゲットレコードを識別するために Get または Scan 操作を使用する DELETE コマンドの実行プランを作成するため、レコードの選択にも同じルールが適用されます。クロスパーティション操作を引き起こす WHERE 句の種類を理解し、そのような操作を回避するには、SELECT を参照してください。
WHERE 句を指定せずにパーティション全体のすべてのレコードを削除する場合は、クロスパーティションスキャンオプションを有効にする必要があります。また、WHERE 句で任意の条件を使用してパーティション全体のレコードを柔軟に削除する場合は、フィルタリングオプションを使用したクロスパーティションスキャンを有効にする必要があります。設定の詳細については、クロスパーティションスキャン設定および ScalarDB Cluster SQL クライアント設定を参照してください。
非 JDBC データベースの場合、SERIALIZABLE 分離レベルでクロスパーティションスキャンを有効にした場合でも、トランザクションは読み取りコミットスナップショット分離 (SNAPSHOT) で実行される可能性があります。これは、より低い分離レベルです。非 JDBC データベースを使用する場合は、トランザクションの一貫性が重要でない場合にのみ、クロスパーティションスキャンを使用してください。
このコマンドは次の列を返します:
updateCount:INT- 削除されたレコードの数
文法
DELETE FROM [<namespace name>.]<table name> [AS <alias>]
[WHERE and_predicates [OR and_predicates ...] | or_predicates [AND or_predicates ...]]
[WITH operation_attributes_or_abac_read_tags_or_abac_write_tags]
identifier: [[<namespace name>.]<table name>.]<column name> | [alias.]<column name>
and_predicates: predicate | (predicate [AND predicate ...])
or_predicates: predicate | (predicate [OR predicate ...])
predicate: <identifier> operator <literal> | <identifier> BETWEEN <literal> AND <literal> | <identifier> [NOT] LIKE <pattern> [ESCAPE <escape character>] | <identifier> IS [NOT] NULL
operator: = | <> | != | > | >= | < | <=
operation_attributes_or_abac_read_tags_or_abac_write_tags: operation_attribute_or_abac_read_tag_or_abac_write_tag [AND operation_attribute_or_abac_read_tag_or_abac_write_tag] ...
operation_attribute_or_abac_read_tag_or_abac_write_tag: operation_attribute | abac_read_tag | abac_write_tag
operation_attribute: <operation attribute name>=<operation attribute value>
abac_read_tag: ABAC_READ_TAG <abac read tag> FOR [POLICY] <abac policy name>
abac_write_tag: ABAC_WRITE_TAG <abac write tag> FOR [POLICY] <abac policy name>
注記
WHERE 句:
WHERE句の任意の列に任意の述語を使用できます。WHERE句では、述語はand_predicatesの OR 形式 (論理和標準形と呼ばれます) またはor_predicatesの AND 形式 (論理積標準形と呼ばれます) である必要があります。- 複数の述語を持つ複数の
and_predicatesまたはor_predicatesを接続する場合は、and_predicatesとor_predicatesを括弧で囲む必要があります。 - バインドマーカー (位置
?および名前:<name>) に<literal>を指定できます。リテラル文法については、リテラルセクションを参照してください。 WHERE句で暗号化された列を指定することはできません。
LIKE 述語:
<pattern>内の_は任意の1文字に一致します。<pattern>内の%は0個以上の文字の任意のシーケンスに一致します。<pattern>内の\はデフォルトでエスケープ文字として機能します。ESCAPE句を指定してエスケープ文字を変更できます。- 空のエスケープ文字
ESCAPE ''を指定してエスケープ文字を無効にすることができます。
主キーを指定した例
たとえば、次のテーブルがあるとします。
CREATE TABLE ns.tbl (
c1 INT,
c2 TEXT,
c3 FLOAT,
c4 BIGINT,
c5 BOOLEAN,
PRIMARY KEY (c1, c2, c3)
) WITH CLUSTERING ORDER BY (c2 DESC, c3 ASC);
DELETE の例は次のとおりです。
-- Delete a record
DELETE FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23;
-- With positional bind markers
DELETE FROM tbl WHERE c1 = ? AND c2 = ? AND c3 = ?;
-- With operations attributes
DELETE FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 WITH 'attribute1' = 'value1' AND 'attribute2' = 'value2';
-- With an ABAC read tag and an ABAC write tag
DELETE FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 WITH ABAC_READ_TAG 'read_tag1' FOR POLICY policy1 AND ABAC_WRITE_TAG 'write_tag1' FOR POLICY policy1;
-- With operations attributes and ABAC read and write tags
DELETE FROM ns.tbl WHERE c1 = 10 AND c2 = 'aaa' AND c3 = 1.23 WITH 'attribute1' = 'value1' AND 'attribute2' = 'value2' AND ABAC_READ_TAG 'read_tag1' FOR POLICY policy1 AND ABAC_WRITE_TAG 'write_tag1' FOR POLICY policy1;
DELETE のステートメントオブジェクトを構築する例は次のとおりです。
// Delete a record
DeleteStatement statement1 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.build();
// With positional bind markers
DeleteStatement statement2 =
StatementBuilder.deleteFrom("tbl")
.where(Predicate.column("c1").isEqualTo(BindMarker.positional()))
.and(Predicate.column("c2").isEqualTo(BindMarker.positional()))
.and(Predicate.column("c3").isEqualTo(BindMarker.positional()))
.build();
// With operations attributes
DeleteStatement statement3 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.withAttribute("attribute1", "value1")
.withAttribute("attribute2", "value2")
.build();
// With an ABAC read tag and an ABAC write tag
DeleteStatement statement4 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.withAbacReadTag("read_tag1", "policy1")
.withAbacWriteTag("write_tag1", "policy1")
.build();
// With operations attributes and ABAC read and write tags
DeleteStatement statement5 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("c1").isEqualTo(Value.of(10)))
.and(Predicate.column("c2").isEqualTo(Value.of("aaa")))
.and(Predicate.column("c3").isEqualTo(Value.of(1.23F)))
.withAttribute("attribute1", "value1")
.withAttribute("attribute2", "value2")
.withAbacReadTag("read_tag1", "policy1")
.withAbacWriteTag("write_tag1", "policy1")
.build();
完全な主キーが指定されていない例
たとえば、次のテーブルがあるとします。
CREATE TABLE ns.user (
id INT,
name TEXT,
age INT,
height FLOAT,
PRIMARY KEY (id)
)
クロスパーティションスキャンフィルタリングを使用した DELETE の例は次のとおりです。
-- Without the WHERE clause to delete all the records of a table
DELETE FROM ns.user;
-- With AND predicates for non-primary key columns
DELETE FROM ns.user WHERE age > 10 AND height > 140;
-- With OR predicates for non-primary key columns
DELETE FROM ns.user WHERE age > 10 OR height > 140;
-- With OR-wise of AND predicates
DELETE FROM ns.user WHERE (age > 10 AND height > 150) OR (age > 15 AND height > 145);
-- With AND-wise of OR predicates
DELETE FROM ns.user WHERE (age < 10 OR age > 65) AND (height < 145 OR height > 175);
-- With LIKE predicates
DELETE FROM ns.user WHERE name LIKE 'A%' OR name NOT LIKE 'B_b';
-- With LIKE predicates with an escape character
DELETE FROM ns.user WHERE name LIKE '+%Alice' ESCAPE '+';
-- With IS NULL predicates
DELETE FROM ns.user WHERE name IS NOT NULL AND age IS NULL;
-- With positional bind markers
DELETE FROM ns.user WHERE age < ?;
DELETE のステートメントオブジェクトを構築する例は次のとおりです。
// Without the WHERE clause to delete all the records of a table
DeleteStatement statement1 = StatementBuilder.deleteFrom("ns", "tbl").build();
// With AND predicates for non-primary key columns
DeleteStatement statement2 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("age").isGreaterThan(Value.of(10)))
.and(Predicate.column("height").isGreaterThan(Value.of(140.0F)))
.build();
// With OR predicates for non-primary key columns
DeleteStatement statement3 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("age").isGreaterThan(Value.of(10)))
.or(Predicate.column("height").isGreaterThan(Value.of(140.0F)))
.build();
// With OR-wise of AND predicates
DeleteStatement statement4 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(
AndPredicateList.predicate(Predicate.column("age").isGreaterThan(Value.of(10)))
.and(Predicate.column("height").isGreaterThan(Value.of(140.0F)))
.build())
.or(
AndPredicateList.predicate(Predicate.column("age").isGreaterThan(Value.of(15)))
.and(Predicate.column("height").isGreaterThan(Value.of(145.0F)))
.build())
.build();
// With AND-wise of OR predicates
DeleteStatement statement5 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(
OrPredicateList.predicate(Predicate.column("age").isLessThan(Value.of(10)))
.or(Predicate.column("age").isGreaterThan(Value.of(65)))
.build())
.and(
OrPredicateList.predicate(Predicate.column("height").isLessThan(Value.of(145.0F)))
.or(Predicate.column("height").isGreaterThan(Value.of(175.0F)))
.build())
.build();
// With LIKE predicates
DeleteStatement statement6 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("name").isLike(Value.of("A%")))
.or(Predicate.column("name").isNotLike(Value.of("B_b")))
.build();
// With LIKE predicates with an escape character
DeleteStatement statement7 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("name").isLike(Value.of("+%Alice"), Value.of("+")))
.build();
// With IS NULL predicates
DeleteStatement statement8 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("name").isNotNull())
.and(Predicate.column("age").isNull())
.build();
// With positional bind markers
DeleteStatement statement9 =
StatementBuilder.deleteFrom("ns", "tbl")
.where(Predicate.column("age").isLessThan(BindMarker.positional()))
.build();
DCL
CREATE USER
CREATE USER コマンドは、指定されたユーザー名、パスワード、およびユーザー属性を持つ新しいユーザーを作成します。
文法
CREATE USER <username> [WITH] {PASSWORD <password> | SUPERUSER | NO_SUPERUSER} ...
- ユーザーにパスワードを指定しない場合、ユーザーはパスワードなしで作成されます。
- ユーザーに
SUPERUSER属性を指定すると、ユーザーはスーパーユーザーになります。 - ユーザーに
NO_SUPERUSER属性を指定すると、ユーザーは通常のユーザーになります。 - ユーザーに
SUPERUSERまたはNO_SUPERUSERのどちらも指定しない場合、ユーザーは通常のユーザーになります。
例
CREATE USER の例は次のとおりです。
-- Create a user with a password as a superuser.
CREATE USER user1 WITH PASSWORD 'password1' SUPERUSER;
-- Create a user with a password.
CREATE USER user2 WITH PASSWORD 'password2';
-- Create a user without a password.
CREATE USER user3;
CREATE USER のステートメントオブジェクトを構築する例は次のとおりです。
// Create a user with a password and the `SUPERUSER` attribute.
CreateUserStatement statement1 =
StatementBuilder.createUser("user1").with("password", UserOption.SUPERUSER).build();
// Create a user with a password.
CreateUserStatement statement2 = StatementBuilder.createUser("user1").with("password").build();
// Create a user without a password.
CreateUserStatement statement3 = StatementBuilder.createUser("user1").build();
ALTER USER
ALTER USER コマンドは、指定されたユーザーのパスワードとユーザー属性を変更します。
文法
ALTER USER <username> [WITH] {PASSWORD <password> | SUPERUSER | NO_SUPERUSER} ...
- ユーザーに
SUPERUSER属性を指定すると、ユーザーはスーパーユーザーになります。 - ユーザーに
NO_SUPERUSER属性を指定すると、ユーザーは通常のユーザーになります。