DatabricksにおけるSQL命令型言語のサポート

これは嬉しい。

現時点ではDatabricksランタイム16.3がベータ版としてリリースされていますが、こちらではSQL手続き型言語がサポートされています。

https://docs.databricks.com/aws/ja/release-notes/runtime/16.3#sql-procedural-language-support

> **SQL命令型言語のサポート**
> ANSI SQL/PSMをベースとしたSQLスクリプティングの機能がパブリックプレビューとなりおました。命令型のロジックを実行するためにSQLを使用することができます。これには、制御フローのステートメント、ローカル変数、例外対応が含まれます。SQLスクリプティングの詳細については、[SQLスクリプティング](https://docs.databricks.com/aws/ja/sql/language-manual/sql-ref-scripting)をご覧ください。

SQLは取得するデータや作成するテーブルを宣言する**宣言型言語**です。どのように処理を実行させるのかを命令するCやPythonのような**命令型言語**のように制御フローを伴う処理の記述は難しく、これまでであれば、Pythonのロジックを含むSQL関数を作成したり、UDF(ユーザー定義関数)を呼び出すなどのアプローチが必要でした。今回のサポートによって、すべてSQLでループや条件分岐のロジックなどを構築することができます。

宣言型と命令型(手続き型)言語の違いはこちらにもまとめられています。

https://docs.databricks.com/aws/ja/data-engineering/procedural-vs-declarative

クラスターを作成する際にランタイムで**16.3 Beta**を選択します。

![Screenshot 2025-03-19 at 8.28.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e6e25fae-b81d-4faf-8b65-d9804e38a47c.png)

テーブルを作成したりするので、カタログとスキーマを選択します。

```sql
%sql
USE takaakiyayoi_catalog.sql_scripting;
```

# 動作確認

最低限の`BEGIN`、`END`構文が動くか確認します。

```sql
%sql
BEGIN
END
```
```
OK
```

動きました。

# ループ処理

ループを用いてテーブルに0-9の10レコードを挿入します。

```sql
%sql
BEGIN
  DECLARE c INT DEFAULT 0;
  CREATE OR REPLACE TABLE t (num INT);
  WHILE c < 10 DO
    INSERT INTO t values (c);
    SET c = c + 1;
  END WHILE;
  SELECT num FROM t ORDER BY num DESC;
END
```

動きました！

![Screenshot 2025-03-19 at 8.35.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/e441fda8-35b4-4c36-87c9-f6999e16e49e.png)

![Screenshot 2025-03-19 at 8.36.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f9c7ffad-8eca-41cc-a037-f15388db19f6.png)

# 条件分岐

`CASE`文を用いた条件分岐を試します。

```sql
%sql
BEGIN
    DECLARE choice INT DEFAULT 3;
    DECLARE result STRING;
    CASE choice
      WHEN 1 THEN
        VALUES ('one fish');
      WHEN 2 THEN
        VALUES ('two fish');
      WHEN 3 THEN
        VALUES ('red fish');
      WHEN 4 THEN
        VALUES ('blue fish');
      ELSE
        VALUES ('no fish');
    END CASE;
  END;
```

`choice`が3なので`red fish`になるはずです。

![Screenshot 2025-03-19 at 8.37.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/2707fd00-7607-4889-8ec8-432c31d39256.png)

これも動きました！

# 複雑な例

アシスタントにコメントをつけてもらいました。2つのテーブルを作成し、レコードを挿入します。`configs`テーブルは`TRUE`が入っているので、給与情報を含めてデータを取得するはずです。

```sql
%sql
BEGIN
  DECLARE shouldReadSalaryConfig BOOLEAN; -- 給与設定を読み込むかどうかのフラグ
  CREATE OR REPLACE TABLE configs (shouldReadSalary BOOLEAN); -- 設定テーブルの作成
  CREATE OR REPLACE TABLE employees (employeeId INT, name STRING, salary FLOAT); -- 従業員テーブルの作成
  
  INSERT INTO configs VALUES (TRUE); -- 設定テーブルに値を挿入
  INSERT INTO employees VALUES (1, "Peter", 45455.75); -- 従業員データの挿入
  INSERT INTO employees VALUES (2, "Tim", 74223.50);
  INSERT INTO employees VALUES (3, "Steve", 80100.00);
  INSERT INTO employees VALUES (4, "Joey", 105783.00);

  SET shouldReadSalaryConfig = (SELECT shouldReadSalary FROM configs); -- 設定を取得

  IF shouldReadSalaryConfig THEN -- 給与設定を読み込む場合
    SELECT employeeId, name, salary FROM employees ORDER BY employeeId; -- 給与を含む従業員情報を取得
  ELSE -- 給与設定を読み込まない場合
    SELECT employeeId, name from employees ORDER BY employeeId; -- 給与を含まない従業員情報を取得
  END IF;
END
```

期待通りに動作しました！

|employeeId|name|salary|
|---|---|---|
|1|Peter|45455.75|
|2|Tim|74223.5|
|3|Steve|80100|
|4|Joey|105783|

SQLの強力なテーブル操作能力と、命令型言語を組み合わせることで、これまで以上に柔軟なデータ操作が可能になります。是非ご活用ください！

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks))をご覧ください。

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)