From a query I want to replace the null values of the "cod_account" field, the condition to fill this field is that it must take the previous value only if it satisfies that the previous records of other fields (cod_agen, cod_sub, no_prod) are equal.
Currently it is like this:
enter image description here
what is desired is
enter image description here
thanks for your advice. i solve it
use with to separate queries.
select
case when cod_account is null and class ='Primary'
then null
when cod_account is null and class='Secundary'
then (select cod_account from principals P--principals is table create in a "with"
where fa.cod_agen=P.cod_agen
and fa.cod_sub=P.cod_sub
and fa.no_prod=P.no_prod
and p.class='secundary'
)
...
from signs fa
create table test
(
id varchar2(10) check( length(trim(id)) > 0),
primary key(id)
)
insert into test values (' '); -- this works
I expected this check constraint to stop this insert. But, it gets inserted none the less. Why ?
Problem is TRIM(' ') returns NULL and LENGTH(NULL) also gives NULL (not 0)
Try NVL(LENGTH(TRIM(' ')), 0) > 0 or
Try TRIM(ID) IS NOT NULL
Snippet stating that constraints can return null aka 'unknown' and considered to be NOT VIOLATING the constraint. Only a return of false violates a constraint. At least as per Oracle 12c
See Oracle Concept page about constraints
Explanation for what you saw:
If str is made up entirely of spaces, then trim(str) is the empty string.
Oracle treats the "empty string" the same as null (of varchar2 data type, when that matters), in flagrant violation of the SQL standard. Oracle is not even consistent in this - there are (very few) exceptions where the empty string is, in fact, seen as "empty string" (for example, in concatenations).
By definition, the length of null is null (in particular, not zero).
In SQL, a condition like null > 0 evaluates to unknown (in the three-valued logic needed to accommodate null in such conditions).
In check constraints unknown is treated the same as true. This is different from the treatment in other conditions (in SQL statements - in where clauses, join conditions etc.), where unknown is treated the same as false. This is documented, for example, here: https://docs.oracle.com/cd/B19306_01/server.102/b14200/clauses002.htm - see the first paragraph in the Check Constraints section.
The correct solution to your problem:
Checking if something is null should be done DIRECTLY, with the is null or is not null conditions. Don't use length for that.
Like this:
check( trim(id) is not null )
I have a date column that i've turned into a checkbox. How do I make it so when the date isn't null the checkbox is checked and if it is null then make it unchecked?
I'd rather keep my DATE column as is, but make it hidden. Create another - checkbox item - and create (two?) trigger(s):
POST-QUERY (which fires when you query existing data)
WHEN-VALIDATE-ITEM (which fires when you modify data on the screen)
if you keep the date column hidden, maybe you don't need it. Or, you do if that date column is modified by some process
Trigger code is simple (presuming that 0 means "not checked" and 1 means "checked"):
:block.checkbox_item := case when :block.date_column is null then 0
else 1
end;
If your Forms version doesn't speak CASE, use DECODE instead (it requires the SELECT statement):
select decode(:block.date_column, null, 0, 1)
into :block.checkbox_item
from dual;
My before update trigger is not creating any history for changing null value to any other value. It is creating history for changing any other values.
My main logic is like this:
if nvl(:old.place,null) <> nvl(:new.place,null) then
insert into table (place)
values(:old.place)
end if;
The NVL() function is used to substitute a value in place of null. You're replacing null with... null, which is pointless. You're then trying to compare two null values with the (in)equality operator, and as null is neither equal to or not equal to anything including itself, the result is unknown, and your condition is always false if either the old or new value is null.
You could use a fixed dummy value that you know will never actually exit:
if nvl(:old.place,'**fake**') <> nvl(:new.place,'**fake**') then
But for clarity I'd generally prefer to explicitly test for nulls:
if (:old.place is null and :new.place is not null)
or (:old.place is not null and :new.place is null)
or (:old.place != :new.place) then
I have an Oracle database, and a table with several not null columns, all with default values.
I would like to use one insert statement for any data I want to insert, and don't bother to check if the values inserted are nulls or not.
Is there any way to fall back to default column value when null is inserted?
I have this code:
<?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)
";
}
So, I have to omit the column entirely, or I will have the error "trying insert null to not null column".
Of course I have multiple nullable columns, so the code create insert statement is very unreadable, ugly, and I just don't like it that way.
I would like to have one statement, something similar to:
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) );
That of course is a hypothetical query. Do you know any way I would achieve that goal with Oracle DBMS?
EDIT:
Thank you all for your answers. It seams that there is no "standard" way to achieve what I wanted to, so I accepted the IMO best answer: That I should stop being to smart and stick to just omitting the null values via automatically built statements.
Not exactly what I would like to see, but no better choice.
For those who reading it now:
In Oracle 12c there is new feature: DEFAULT ON NULL. For example:
CREATE TABLE tab1 (
col1 NUMBER DEFAULT 5,
col2 NUMBER DEFAULT ON NULL 7,
description VARCHAR2(30)
);
So when you try to INSERT null in col2, this will automatically be 7.
As explained in this AskTom thread, the DEFAULT keyword will only work as a stand-alone expression in a column insert and won't work when mixed with functions or expressions such as NVL.
In other words this is a valid query:
INSERT INTO schema.my_table
( pk_column, other_column, not_null_column_with_default_value)
VALUES
(:pk_column,:other_column, DEFAULT)
You could use a dynamic query with all rows and either a bind variable or the constant DEFAULT if the variable is null. This could be as simple as replacing the string :not_null_column_with_default_value with the string DEFAULT in your $insert.
You could also query the view ALL_TAB_COLUMNS and use nvl(:your_variable, :column_default). The default value is the column DATA_DEFAULT.
I think the cleanest way is to not mention them in your INSERT-statement. You could start writing triggers to fill default values but that's heavy armor for what you're aiming at.
Isn't it possible to restructure your application code a bit? In PHP, you could construct a clean INSERT-statement without messy if's, e.g. like this:
<?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);
?>
The better option for performance is the first one.
Anyway, as I understand, you don't want to repeat the insert column names and values due the difficult to make modifications. Another option you can use is to run an insert with returning clause followed by an update:
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
It seems to work with PHP.
After this you can check for null on insered_value bind variable. If it's null you can run the following update:
UPDATE my_table
SET not_null_column_with_default_value = DEFAULT
WHERE pk_column = :pk_column:
I would like to use one insert
statement for any data I want to
insert, and don't bother to check if
the values inserted are nulls or not.
Define your table with a default value for that column. For example:
create table myTable
(
created_date date default sysdate,
...
)
tablespace...
or alter an existing table:
alter table myTable modify(created_date default sysdate);
Now you (or anyone using myTable) don't have to worry about default values, as it should be. Just know that for this example, the column is still nullable, so someone could explicitly insert a null. If this isn't desired, make the column not null as well.
EDIT: Assuming the above is already done, you can use the DEFAULT keyword in your insert statement. I would avoid triggers for this.