2011-03-22 227 views
8

我有一个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) 
    ";   
} 

所以,我完全忽略该列,或将我的错误“试图插入空不空列”。 当然,我有多个可为空的列,所以创建插入语句的代码非常难读,难看,我只是不喜欢这种方式。

我想有一个说法,类似于:

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的最佳答案:我应该停止聪明并坚持只通过自动构建的语句省略空值。

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

+0

你为什么不输入列的默认值“not_null_column_with_default_value”,而不是“默认”一词在“假设查询”里面? – palindrom 2011-03-22 09:06:34

+0

原因我不知道插入时默认值是多少。但是@Vincent Malgrat建议我可以获取这种形式ALL_TAB_COLUMNS – SWilk 2011-03-22 09:54:34

回答

11

对于那些现在读它谁:

在Oracle 12c中有新的特点:DEFAULT ON NULL。例如:

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

所以,当您尝试插入空COL2,这将自动为7

2

如在此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中用字符串DEFAULT替换字符串:not_null_column_with_default_value一样简单。

您还可以查看视图ALL_TAB_COLUMNS并使用nvl(:your_variable, :column_default)。默认值是DATA_DEFAULT列。

+0

感谢您对data_default的建议。我想我会创建一个函数'get_default(:schema,:table,:column)'这将利用oracle缓存,所以我不应该很慢。我只需要检查类型是否可以毫无问题地转换为其他类型。 – SWilk 2011-03-22 09:52:39

+1

@SWilk:类型是旧的CLOB。这只是文本,应该转换为字符串。在你的查询中,你应该*用这个列的值替换* DEFAULT,而不是* bind *这个值,因为默认值可以是一个表达式(比如'trunc(sysdate)+ 1') – 2011-03-22 10:29:10

+0

好点,谢谢。 – SWilk 2011-03-22 12:00:52

1

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

是不是有可能重构你的应用程序代码?在PHP中,你可以构造一个干净的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); 
?> 
+0

然后“奥尼尔”作为价值和BUM!如果转换为绑定变量(:值),那实际上会工作。无论如何,我知道这种模式,但我正在寻找任何可以完成这项工作的预言。我认为oracle可能会为此做好准备。 – SWilk 2011-03-22 09:36:12

+0

@SWilk你是对的。我的例子可以很容易地修改为使用绑定变量。事实上,我只是做了。 – 2011-03-22 12:41:28

0

我想用一个刀片 语句我想 插入任何数据,也懒得检查,如果 插入的值为空或没有。

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

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

或变更现有的表:

alter table myTable modify(created_date default sysdate); 

现在你(或使用人myTable的),不必担心默认值,因为它应该是。只要知道,在这个例子中,列仍然可以为空,所以有人可以显式插入null。如果不需要,请使该列不为空。

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

+0

这些列具有默认值。问题是我想在绑定变量为null时插入默认值。'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语句。 – SWilk 2011-03-22 11:05:12

+0

好的,我现在明白了。不幸的是,你可能不会找到一个有说服力的解决方案,让所有列的主插入为空或不是。如果您无法根据哪些列为空值来更改插入标记,那么之前的插入触发器将是下一个最好的事情。请记住,如果一列从非空变为空,那么你也必须改变触发器以使用该列的默认值排除。 (增加额外的维护开销以及处理开销)。 – tbone 2011-03-22 11:46:10

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 

这似乎work with PHP

之后您可以检查上的null绑定变量。如果是空,你可以运行以下更新:

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