Field autoincrement for Oracle without trigger with Slick? - oracle

I am trying to insert rows in a ErrorTable which has a few fields plus an idError which is supossed to be the primary key. I need idError to be autoincremented. However one requirement is we cannot use a trigger, so using O.AutoInc would not work for us.
We also tried to use plain sql using a sequence. However we have two blob fields which makes the query too long ( getting the string literal too long error).
Any idea about how to attack this problem? I am also considering to use UUID.
Note: we are using oracle-xe-11g

In 11g you can have only implement an auto-incrementing identifier with a trigger. So it seems your requirements rule out anything except SYS_GUID. Find out more.
" it also represents another query to get that value "
Not necessarily. If you have the option to define the target table you can set a default values for the UUID column like this:
create table t23 (
id raw(16) default sys_guid() not null primary key
, col1 varchar2(10)
);
Then
SQL> insert into t23 (col1) values ('ABC');
1 row created.
SQL> select * from t23;
ID COL1
-------------------------------- -----------
7DD7216E731C126537615FE1244B4B50 ABC
SQL>
Note: tested on 12C but should work in earlier versions.

Related

Apex Oracle How To Create Conditional Column

I am new to using Apex Oracle to create a table and insert values in it. I need to create a column that is only mandatory if the value for another column is "Y" (if it is "N", then it is not mandatory). The type of the other column is a CHAR with length 1. How could I do this? Would this be done in SQL Scripts or SQL Commands? Similarly, is there a way to delete old SQL commands that were used (that now I realize are incorrect)?
Thank you!
Welcome to Oracle APEX and Stack Overflow. You can create objects (tables/views) in both SQL commands and SQL Scripts. For ad hoc creating, SQL Commands is probably easier. To remove (called "drop" in oracle) objects that you create, that can be done in SQL Commands, or even easier in the "Object Browser" - locate the object and select "drop". Note that this cannot be undone.
About the requirement for a column to be conditionally mandatory:
This can be enforced in the database using a check constraint.
CREATE TABLE test_table (
id NUMBER GENERATED AS IDENTITY,
col1 VARCHAR2(1),
col2 VARCHAR2(10));
Table TEST_TABLE created.
ALTER TABLE test_table ADD CONSTRAINT test_table_c1
CHECK ((col1 = 'Y' AND col2 IS NOT NULL) or (col1 != 'Y'));
Table TEST_TABLE altered.
INSERT INTO test_table(col1,col2) VALUES ('N',NULL);
1 row inserted.
INSERT INTO test_table(col1,col2) VALUES ('Y',NULL);
INSERT INTO test_table(col1,col2) VALUES ('Y',NULL)
Error report -
ORA-02290: check constraint (SAMPLEAPPS.TEST_TABLE_C1) violated
INSERT INTO test_table(col1,col2) VALUES ('Y','Some Value');
1 row inserted.

Oracle 11g - "DEFAULT ON NULL"?

I am running Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production, I am trying to find an equivalent to 12c's "DEFAULT ON NULL" for a table. Basically I have to create a table where the requirement is than whenever someone intentionally or inadvertently passes a NULL value, it is replaced with a DEFAULT value (in this case a NUMBER type equal to 1). Is there any easy way to do this in 11g? I know I could do a trigger on the table, but I would have to put in logic for every single column, and that seems ridiculous.
My table definition currently looks like this:
CREATE TABLE MYTABLE
(
FLAG NUMBER(1) DEFAULT 0
)
If I explicitly pass in null it WILL get stored. In that situation I was expecting the default value to be placed instead.
You can use simple 'DEFAULT' behavior for columns and don't provide anything when inserting.
CREATE TABLE table1 (
id NUMBER(8.0) NOT NULL,
col1 NUMBER(8.0) NOT NULL DEFAULT 10,
col2 NUMBER(8.0) NOT NULL DEFAULT 20,
PRIMARY KEY (id);
);
INSERT INTO table1 (id) values (123); //will result in creating a row with default values.
Also if you're using some kind of ORM you can use dynamic insert and dynamic update options. This way if you don't provide values on insert they will be set to defaults;
and on update the unchanged values will not be included into query.
This is how you can bypass explicit null values in query and defaults will apply.

Alter table after keyword in Oracle

ALTER TABLE testTable ADD column1 NUMBER(1) DEFAULT 0 NOT NULL AFTER column2;
Why can't I use mySql syntax in Oracle too? The above command works in MySql. Can you give me an equivalent that works?
Error report:
SQL Error: ORA-01735: invalid ALTER TABLE option
01735. 00000 - "invalid ALTER TABLE option"
I am asking if there is any way to use after clause in Oracle command that I provided?
Because SQL is a relational algebra. It doesn't care one bit about "where" columns are located within a table, only that they exist.
To get it to work in Oracle, just get rid of the after clause. The Oracle documentation for alter table is here but it boils down to:
alter table testTable
add ( column1 number(1) default 0 not null )
There is no after clause for the alter table command.
Oracle does not support adding columns in the middle of a table, only adding them to the end. Your database design and app functionality should not depend on the order of columns in the database schema. You can always specify an order in your select statement, after all.
However if for some reason you simply must have a new column in the middle of your table there is a work around.
CREATE TABLE tab1New AS SELECT 0 AS col1, col1 AS col2 FROM tab1;
DROP TABLE tab1 PURGE;
RENAME tan1New to tab1;
Where the SELECT 0 AS col1 is your new column and then you specify other columns as needed from your original table. Put the SELECT 0 AS col1 at the appropriate place in the order you want.
Afterwards you may want to run an alter table statement on the column to make sure it's the data type you desire.
Try this :
ALTER TABLE testTable ADD column1 NUMBER(1) DEFAULT 0 NOT NULL

Add NOT NULL LOB column without default in Oracle

I am trying to add a CLOB column to a table (change a VARCHAR to a CLOB actually, but it only seems possible by adding a new column, copying and dropping the old). The column should be NOT NULL without a default value (and the table is not empty). How can I achieve this?
My original idea was to create the column with a dummy default, and change that later, but that does not seem possible:
ALTER TABLE foo RENAME COLUMN text TO text_temp;
ALTER TABLE foo ADD (
text CLOB DEFAULT '*' NOT NULL
);
UPDATE foo SET text = text_temp;
ALTER TABLE foo DROP COLUMN text_temp;
ALTER TABLE foo MODIFY (
text CLOB NOT NULL
);
-- ORA-22296: invalid ALTER TABLE option for conversion of LONG datatype to LOB
I also tried defining the column as text CLOB and adding the NOT NULL constraint later, but it gave the same error. Is there a way of doing this, short of recreating the whole table?
Does
ALTER TABLE foo MODIFY text DEFAULT NULL;
work for you?
When adding or removing a default value or a NOT NULL constraint, you don't need to specify the datatype of the column.
EDIT: To quote the Oracle documentation on ALTER TABLE:
If a column has a default value, then you can use the DEFAULT clause to change the default to NULL, but you cannot remove the default value completely. If a column has ever had a default value assigned to it, then the DATA_DEFAULT column of the USER_TAB_COLUMNS data dictionary view will always display either a default value or NULL.
This should explain why you're seeing a difference in SQL Developer.
However, I don't believe there's a significant difference between specifying DEFAULT NULL for a column and not specifying a default value. In both cases, a null value will be assumed for any column not explicitly given a value in an INSERT statement.
You are declaring the column as NOT NULL when you added it to the table, so you don't need to make it NOT NULL again. I think if you corrected the syntax in the final MODIFY clause you would still get an error, albeit a different one (precise number eludes me right now).
But what you are trying to acheive is definitely possible, with the right syntax :)
SQL> alter table t23 add ctxt clob
2 /
Table altered.
SQL> update t23 set ctxt = txt
2 /
2 rows updated.
SQL> alter table t23 modify ctxt not null
2 /
Table altered.
SQL> alter table t23 drop column txt
2 /
Table altered.
SQL> alter table t23 rename column ctxt to txt
2 /
Table altered.
SQL>

Insert into oracle database

Hi I have a database with loads of columns and I want to insert couple of records for testing, now in order to insert something into that database I'd have to write large query .. is it possible to do something like this
INSERT INTO table (SELECT FROM table WHERE id='5') .. I try to insert the row with ID 5 but I think this will create a problem because it will try to duplicate a record, is it possible to change this ID 5 to let say 1000 then I'd be able to insert data without writing complex query and while doing so avoiding replication of data .. tnx
In PL/SQL you can do something like this:
declare
l_rec table%rowtype;
begin
select * into l_rec from table where id='5';
l_rec.id := 1000;
insert into table values l_rec;
end;
If you have a trigger on the table to handle the primary key from a sequence (:NEW.id = seq_sequence.NEXTVAL) then you should be able to do:
INSERT INTO table
(SELECT columns_needed FROM table WHERE whatever)
This will allow you to add in many rows at one (the number being limited by the WHERE clause). You'll need to select the columns that are required by the table to be not null or not having default values. Beware of any unique constraints as well.
Otherwise you'll be looking at PL/SQL or some other form of script to insert multiple rows.
For each column that has no default value or you want to insert the values other than default, you will need to provide the explicit name and value.
You only can use an implicit list (*) if you want to select all columns and insert them as they are.
Since you are changing the PRIMARY KEY, you need to enumerate.
However, you can create a before update trigger and change the value of the PRIMARY KEY in this trigger.
Note that the trigger cannot reference the table itself, so you will need to provide some other way to get the unique number (like a sequence):
CREATE TRIGGER trg_mytable_bi BEFORE INSERT ON mytable FOR EACH ROW
BEGIN
:NEW.id := s_mytable.nextval;
END;
This way you can use the asterisk but it will always replace the value of the PRIMARY KEY.

Resources