【问题标题】:Insert default value when null is inserted插入 null 时插入默认值
【发布时间】:2011-07-20 07:32:56
【问题描述】:

我有一个 Oracle 数据库和一个包含多个非空列的表,所有列都具有默认值。

我想对我想要插入的任何数据使用一个插入语句,并且不费心检查插入的值是否为空值。

有没有办法在插入 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 列”。 当然我有多个可以为空的列,所以代码 create insert 语句非常不可读,丑陋,我就是不喜欢那样。

我想要一个声明,类似于:

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) );

这当然是一个假设的查询。您知道我可以通过什么方式使用 Oracle DBMS 实现该目标吗?

编辑

谢谢大家的回答。似乎没有“标准”方式来实现我想要的,所以我接受了 IMO 的最佳答案:我应该停止聪明,坚持通过自动构建的语句省略空值。

不完全是我想看到的,但没有更好的选择。

【问题讨论】:

  • 为什么不在“假设查询”中输入“not_null_column_with_default_value”列的默认值而不是“DEFAULT”一词?
  • 因为我不知道插入时的默认值是什么。但正如@Vincent Malgrat 建议的那样,我可以获取该表格 ALL_TAB_COLUMNS

标签: oracle default notnull


【解决方案1】:

正如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)

您可以对所有行使用动态查询,如果变量为空,则可以使用绑定变量或常量 DEFAULT。这可以像在 $insert 中将字符串 :not_null_column_with_default_value 替换为字符串 DEFAULT 一样简单。

您也可以查询视图ALL_TAB_COLUMNS 并使用nvl(:your_variable, :column_default)。默认值为DATA_DEFAULT 列。

【讨论】:

  • 感谢您对 data_default 的建议。我想我会创建一个函数get_default(:schema,:table,:column),它将利用oracle 缓存,所以我应该不会很慢。我只需要检查 类型是否可以毫无问题地转换为其他类型。
  • @SWilk: 类型是旧的 CLOB。它只是文本,应转换为字符串。在您的查询中,您应该用该列的值替换 DEFAULT,而不是绑定该值,因为默认值可以是表达式(例如trunc(sysdate)+1)跨度>
  • 在数据字典中查询每个插入的默认值肯定会破坏您的性能。只有当插入性能对您的应用程序来说不是问题时,我才会使用它。
【解决方案2】:

我认为最简洁的方法是在您的 INSERT 语句中不提及它们。你可以开始编写触发器来填充默认值,但这对于你的目标来说是沉重的盔甲。

难道不能稍微重构一下您的应用程序代码吗?在 PHP 中,您可以构造一个干净的 INSERT 语句,而不会出现混乱的 if 语句,例如像这样:

<?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);
?>

【讨论】:

  • 然后“奥尼尔”作为价值和 BUM 出现!如果转换为绑定变量(:值),那实际上会起作用。无论如何,我知道这种模式,但我一直在寻找可以完成这项工作的任何类型的 oracle 语句。我认为 oracle 可能对此有现成的解决方案。
  • @SWilk 你是对的。我的示例可以很容易地修改为使用绑定变量。事实上,我只是这样做了。
【解决方案3】:

我想使用一个插入 我想要的任何数据的声明 插入,不要费心检查是否 插入的值是否为空。

使用该列的默认值定义您的表格。例如:

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

或更改现有表:

alter table myTable modify(created_date default sysdate);

现在您(或任何使用 myTable 的人)不必担心默认值,因为它应该是。只要知道对于这个例子,列仍然可以为空,所以有人可以显式地插入一个空值。如果不希望这样做,请将该列也设为不为空。

编辑:假设以上已经完成,您可以在插入语句中使用 DEFAULT 关键字。我会避免触发这个。

【讨论】:

  • 列有默认值。问题是我想在绑定变量为空时插入默认值。 insert into tmp_table_tab (aaa,bbb,ccc) values(9, 8, nvl(:my_value,DEFAULT)) 导致 ORA-00936 缺少表达式。虽然insert into tmp_table_tab (aaa,bbb,ccc) values(9, 8, DEFAULT) 会正确执行,但它会做一些我不需要的事情。我想忘记 :my_Value 的值,并为所有插入使用一个 INSERT 语句。
  • 好的,我现在明白了。不幸的是,您可能不会找到一个雄辩的解决方案来为所有列都插入一个主插入为空或不为空。如果您不能根据哪些列是空值来更改您的插入 stmt,那么插入前触发器将是下一个最佳选择。请记住,如果一列从非空更改为可空,那么您还必须更改触发器以使用该列的默认值排除。 (增加额外的维护开销和处理开销)。
【解决方案4】:

性能更好的选择是第一个。

无论如何,据我了解,由于难以进行修改,您不想重复插入列名称和值。您可以使用的另一个选项是运行带有 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

好像是work with PHP

在此之后,您可以在 insered_value 绑定变量上检查 null。如果它为空,您可以运行以下更新:

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

【讨论】:

    【解决方案5】:

    对于现在正在阅读它的人:

    在 Oracle 12c 中有一个新特性:DEFAULT ON NULL。例如:

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

    所以当你尝试在 col2 中插入 null 时,它会自动为 7。

    【讨论】:

      猜你喜欢
      • 2016-08-30
      • 2013-01-14
      • 2014-11-19
      • 2015-05-27
      • 1970-01-01
      • 1970-01-01
      • 2015-05-24
      • 1970-01-01
      • 2020-10-12
      相关资源
      最近更新 更多