web-dev-qa-db-ja.com

nullが挿入されたときにデフォルト値を挿入する

Oracleデータベースと、null以外の列がいくつかあり、すべてデフォルト値のテーブルがあります。

挿入したいデータに対して1つの挿入ステートメントを使用したいので、挿入された値がnullであるかどうかをわざわざチェックする必要はありません。

Nullが挿入されたときにデフォルトの列値にフォールバックする方法はありますか?

私はこのコードを持っています:

<?php
if (!empty($values['not_null_column_with_default_value'])) {
    $insert = "
        INSERT INTO schema.my_table
            ( pk_column, other_column, not_null_column_with_default_value)
        VALUES
            (:pk_column,:other_column,:not_null_column_with_default_value)
     ";
} else {
    $insert = "
        INSERT INTO schema.my_table
            ( pk_column, other_column)
        VALUES
            (:pk_column,:other_column)
     ";        
}

そのため、列を完全に省略する必要があります。そうしないと、「null列をnullに挿入しようとしています」というエラーが発生します。もちろん、私は複数のnull許容列を持っているので、コードcreate insertステートメントは非常に読みにくく、醜く、そのようにそれが好きではありません。

次のようなステートメントが1つあります。

INSERT INTO schema.my_table
    ( pk_column, other_column, not_null_column_with_default_value)
VALUES
    (:pk_column,:other_column, NVL(:not_null_column_with_default_value, DEFAULT) );

もちろん、これは架空のクエリです。 OracleDBMSでその目標を達成する方法を知っていますか?

[〜#〜]編集[〜#〜]

ご回答ありがとうございます。私が望んでいたことを達成するための「標準的な」方法がないことを縫い合わせたので、IMOのベストアンサーを受け入れました。

正確には私が見たいものではありませんが、より良い選択はありません。

12
SWilk

今それを読んでいる人のために:

Oracle 12cには、新機能があります: DEFAULT ON NULL 。例えば:

CREATE TABLE tab1 (
  col1        NUMBER DEFAULT 5,
  col2        NUMBER DEFAULT ON NULL 7,
  description VARCHAR2(30)
);

したがって、col2にnullを挿入しようとすると、これは自動的に7になります。

14
Lisa Aaron

この AskTom thread で説明されているように、DEFAULTキーワードは、列挿入のスタンドアロン式としてのみ機能し、NVLなどの関数または式と混合した場合は機能しません。

言い換えれば、これは有効なクエリです。

_INSERT INTO schema.my_table
    ( pk_column, other_column, not_null_column_with_default_value)
VALUES
    (:pk_column,:other_column, DEFAULT)
_

すべての行と、バインド変数または変数がnullの場合は定数DEFAULTのいずれかで動的クエリを使用できます。これは、_:not_null_column_with_default_value_の文字列_$insert_を文字列DEFAULTに置き換えるのと同じくらい簡単です。

ビュー_ALL_TAB_COLUMNS_をクエリして、nvl(:your_variable, :column_default)を使用することもできます。デフォルト値は列_DATA_DEFAULT_です。

3
Vincent Malgrat

パフォーマンスのためのより良いオプションは最初のものです。

とにかく、私が理解しているように、変更を加えるのは難しいので、挿入列の名前と値を繰り返したくありません。使用できるもう1つのオプションは、 returning 句を指定して挿入を実行し、その後に更新を実行することです。

INSERT INTO schema.my_table
    ( pk_column, other_column, not_null_column_with_default_value)
VALUES
    (:pk_column,:other_column, :not_null_column_with_default_value)
RETURNING not_null_column_with_default_value 
INTO :insered_value

PHPで動作する のようです。

この後、insered_valueバインド変数でnullを確認できます。 nullの場合は、次の更新を実行できます。

UPDATE my_table
   SET not_null_column_with_default_value  = DEFAULT
 WHERE  pk_column = :pk_column: 
1
FerranB

最もクリーンな方法は、INSERTステートメントでそれらについて言及しないことだと思います。デフォルト値を埋めるためにトリガーを書き始めることもできますが、それはあなたが目指しているものにとっては重装甲です。

アプリケーションコードを少し再構築することはできませんか? PHPでは、面倒なifを使用せずに、クリーンなINSERTステートメントを作成できます。このような:

<?php
$insert['column_name1'] = 'column_value1';
$insert['column_name2'] = 'column_value2';
$insert['column_name3'] = '';
$insert['column_name4'] = 'column_value4';

// remove null values
foreach ($insert as $key => $value) {
  if (is_null($value) || $value=="") {
    unset($insert[$key]);
  }
}

// construct insert statement
$statement = "insert into table (". implode(array_keys($insert), ',') .") values (:". implode(array_keys($insert), ',:') .")";

// call oci_parse
$stid = oci_parse($conn, $statement);

// bind parameters
foreach ($insert as $key => $value) {
  oci_bind_by_name($stid, ":".$key, $value);
}

// execute!
oci_execute($stid);
?>
1

挿入したいデータに対して1つの挿入ステートメントを使用したいので、挿入された値がnullであるかどうかをわざわざチェックする必要はありません。

その列のデフォルト値を使用してテーブルを定義します。例えば:

create table myTable
(
  created_date date default sysdate,
  ...
)
tablespace...

または既存のテーブルを変更します。

alter table myTable modify(created_date default sysdate);

これで、あなた(またはmyTableを使用している人)は、デフォルト値について心配する必要がなくなりました。この例では、列はまだnull可能であるため、誰かが明示的にnullを挿入する可能性があることを知っておいてください。これが望ましくない場合は、列もnullにしないようにします。

編集:上記がすでに行われていると仮定すると、挿入ステートメントでDEFAULTキーワードを使用できます。私はこれの引き金を避けます。

0
tbone