概要
Databricks へ Oracle Database における長さが0(ゼロ)の文字値を NULL として処理される仕様の移行方法を共有します。
Oracle Database のドキュメントにて、長さが0(ゼロ)の文字値が NULL となる旨が次のように記載されております。
Oracle Databaseは、長さが0(ゼロ)の文字値をNULLとして処理します。
Databricks においては、 '' が '' として保持されるため、追加の処理が必要となります。
src_schema = "str_col string"
src_data = [
{"str_col": "a"},
{"str_col": ""},
{"str_col": " "},
]
df = spark.createDataFrame(src_data, src_schema)
print(df.collect())
df.display()
Oracle Database の動作確認
長さが0(ゼロ)の文字値が NULL となることを確認
Oracle Database にて以下のクエリを実行したところ、'' が NULL となりました。
WITH src AS (
SELECT 'a' AS str_col FROM DUAL
UNION ALL
SELECT '' AS str_col FROM DUAL
UNION ALL
SELECT ' ' AS str_col FROM DUAL
)
SELECT
*
FROM src
;
Databricks への移行
長さが0(ゼロ)の文字値が NULL となるような処理を追加
from pyspark.sql.functions import expr
def convert_zero_byte_to_null(
df,
tgt_col_names,
):
with_cols_conf = {}
for col_name in tgt_col_names:
with_cols_conf[col_name] = expr(
f"""
CASE
WHEN {col_name} = ''
THEN NULL
ELSE
{col_name}
END
"""
)
df = df.withColumns(with_cols_conf)
return df
tgt_col_names = ["str_col"]
modifed_df = convert_zero_byte_to_null(
df,
tgt_col_names,
)
print(modifed_df.collect())
modifed_df.display()
注意事項
1. 固定長形式のファイルを CHAR 型のカラムに TRIM せずに書き込む処理を移行する場合の注意事項
固定長形式のファイルを TRIM せずに CHAR 型のカラムに対して書き込む処理を移行する際には、該当するカラムに本記事の処理を実施しないでください。
Oracle Database の CHAR 型カラムへ書きこみ仕様を下記クエリで確認すると、""
(空文字)が NULL となり、" "
(スペース)は" "
(スペースが5つ)となりました。固定長形式のファイルを TRIM せずに CHAR型へ書き込む際には、Oracle Database では指定桁数のスペースを保持することとなります。
WITH src AS(
SELECT '空文字' AS col_type, CAST('' AS char(5)) AS value FROM DUAL
UNION ALL
SELECT 'スペース' AS col_type, CAST(' ' AS char(5)) AS value FROM DUAL
)
SELECT
*
FROM
src
;
CHAR 型のカラムを Oracle Database から Databricksへ移行する際には、桁数分のスペースを保持させずに、TRIM して保持することが多いです。その変更仕様に基づき TRIM されたカラムに対して、本記事の処理を適用すると、NULL となってしまうため想定外の動作となる可能性があります。固定長形式のファイルがソースであり TRIM されていない CHAR 型のカラムに対しては、``(空文字)を NULL に変換しないようにしてください。