I have order table with these columns:
id, customerid, orderdate, createusername, createdatetime
createusername and createdatetime aren't displayed in edit form - I want to set their values on form submit.
Set their default values to
:APP_USER for createusername
SYSDATE for createdatetime
Usually this is done with a trigger on the table. That way you don't have to worry about this anywhere in your apex application. That trigger would be something like this:
create or replace trigger order_biu
before insert or update
on order
for each row
begin
:new.createdatetime := sysdate;
:new.createusername := nvl(sys_context('APEX$SESSION','APP_USER'),user);
end order_biu;
/
I assumed that the column order.createdatetime is of datatype DATE. For other datatypes, you'll need another default value.
How to increment the value of the unique constraint column value in ORACLE, in the select statement.
For example, in a table 'BILLING_TABLE' - column BLNG_Sk is the unique key (Autoincremented).
So while inserting a new record into the BILLING_TABLE, for the column BLNG_SK we need to give the value (Which is the increment by 1 from the present max value.)
For example, if BLNG_SK max value is 12321.
new record should be 12322.
how to achieve this in Oracle?
Oracle has a SEQUENCE object which provides the functionality you require.
You create one using the CREATE SEQUENCE SQL statement.
The Oracle documentation provides all the required information and the documentation is available via Oracle's Web site.
Assuming you are on Oracle 12.1 or later, define it as an identity column and do not pass any value when inserting:
create table testtable
( test_id number generated always as identity
constraint testtable_pk primary key
, othercol varchar2(10) );
insert into testtable (othercol) values ('Demo');
select * from testtable;
TEST_ID OTHERCOL
---------- ----------
1 Demo
insert into testtable (othercol) values ('Demo #2');
select * from testtable;
TEST_ID OTHERCOL
---------- ----------
1 Demo
2 Demo #2
Try creating a sequence and a trigger. This is the case when you provide the value manually.
CREATE SEQUENCE dept_seq START WITH 12322;
Trigger definition:
CREATE OR REPLACE TRIGGER dept_bir
BEFORE INSERT ON BILLING_TABLE
FOR EACH ROW
BEGIN
SELECT dept_seq.NEXTVAL
INTO :new.id
FROM dual;
END;
/
I would receive an error:
ORA-02437: cannot validate (%s.%s) - primary key violated
Cause: attempted to validate a primary key with duplicate values or null values
I found it was because I have a stored procedure that increments the ID, but it had failed to do so when it re-ran and had an error related to one of my datatypes. I found I now had a duplicate ID in my database table. All this made sense and I was able to easily rectify it with a DELETE FROM MyTable WHERE ID = x, where x was the offending duplicate ID. The problem I have is the only way I was able to even find the IDs that were duplicated is in the first place is because I did a SELECT * FROM MyTable WHERE ID = x -- where x was one greater than the last ID I could actually see. I found it just by an educated guess. So:
Why can't I see these duplicate IDs when I open the table in Oracle SQL Developer? It only shows the last row as the ID before the duplicates. I don't think it is because of my primary key constraint, since the first line in my stored procedure is to remove that (and put it back, at the end - probably when I got my error), and it was not present when I looked at my table.
Is there some way to make these last IDs that got inserted into the table visible, so I wouldn't have to guess or assume that the duplicate IDs are "hiding" as one greater than the last ID I have in my table, in the future? There is a commit; in my stored procedure, so they should have appeared -- unless, of course, the procedure got hung up before it could run that line of code (highly probable).
Stored procedure that runs:
create or replace
PROCEDURE PRC_MYTABLE_INTAKE(
, EMPLOYEE_ID IN NVARCHAR2
, TITLE_POSITION IN NVARCHAR2
, CREATED_DATE IN DATE
, LAST_MODIFIED IN DATE
) AS
myid integer := 0;
appid integer := 0;
BEGIN
-- disable PK constraint so it can be updated
EXECUTE IMMEDIATE 'ALTER TABLE MYTABLE DROP CONSTRAINT MYTABLE_PK';
COMMIT;
-- assign ID to myid
SELECT ID INTO myid FROM MYTABLE WHERE ROWID IN (SELECT MAX(ROWID) FROM MYTABLE);
-- increment
myid := myid + 1;
-- assign APPLICATION_ID to appid
SELECT APPLICATION_ID INTO appid FROM MYTABLE WHERE ROWID IN (SELECT MAX(ROWID) FROM MYTABLE);
-- increment
appid := appid + 1;
-- use these ids to insert with
INSERT INTO MYTABLE (ID, APPLICATION_ID,
, EMPLOYEE_ID
, TITLE_POSITION
, CREATED_DATE
, LAST_MODIFIED
) VALUES(myid, appid,
, EMPLOYEE_ID
, TITLE_POSITION
, CREATED_DATE
, LAST_MODIFIED
);
COMMIT;
-- re-enable the PK constraint
EXECUTE IMMEDIATE 'ALTER TABLE PASS ADD CONSTRAINT MYTABLE_PK PRIMARY KEY (ID)';
COMMIT;
END;
Here's one problem:
SELECT ID
INTO myid
FROM MYTABLE
WHERE ROWID IN (SELECT MAX(ROWID) FROM MYTABLE)
There is no correlation between ID and ROWID, so you're not getting the maximum current ID, you're just getting the one that happens to be on the row that is furthest from the start of a datafile with a high number.
The code you need is:
SELECT COALESCE(MAX(ID),0)
FROM MYTABLE;
Or better yet, just use a sequence.
No idea why you're dropping the PK either.
Furthermore, when you issue the query:
SELECT APPLICATION_ID INTO appid ...
... that could be for a different row than the one you already got the id for, because a change could have been committed to the table.
Of course another issue is that you can't run two instances of this procedure at the same time either.
For David Aldridge, since he wants to look at code instead of the real reason I posted my question, run this ---
CREATE TABLE YOURSCHEMA.TESTING
(
TEST_ID NVARCHAR2(100) NOT NULL
, TEST_TYPE NVARCHAR2(100) NOT NULL
, CONSTRAINT TEST_PK PRIMARY KEY
(
TEST_ID
)
ENABLE
);
create or replace
PROCEDURE PRC_TESTING_INSERT(
TEST_TYPE IN NVARCHAR2
) AS
testid integer := 0;
BEGIN
-- disable PK constraint so it can be updated
EXECUTE IMMEDIATE 'ALTER TABLE TESTING DROP CONSTRAINT TEST_PK';
COMMIT;
-- assign TEST_ID to testid
SELECT TEST_ID INTO testid FROM TESTING WHERE ROWID IN (SELECT MAX(ROWID) FROM TESTING);
-- increment
testid := testid + 1;
-- use this id to insert with
INSERT INTO TESTING (TEST_ID, TEST_TYPE) VALUES(testid, TEST_TYPE);
COMMIT;
-- re-enable the PK constraint
EXECUTE IMMEDIATE 'ALTER TABLE TESTING ADD CONSTRAINT TEST_PK PRIMARY KEY (TEST_ID)';
COMMIT;
END;
SET serveroutput on;
DECLARE
test_type varchar(100);
BEGIN
test_type := 'dude';
YOURSCHEMA.PRC_TESTING_INSERT(test_type);
-- to verify the variable got set and procedure ran, could do:
--dbms_output.enable;
--dbms_output.put_line(test_type);
END;
Now, because there is no data in the table, the stored procedure will fail with ORA-06512: no data found. If you then try and run it again, you will get ORA-02443: cannot drop constraint - nonexistent constraint, because the EXECUTE IMMEDIATE 'ALTER TABLE TESTING DROP CONSTRAINT TEST_PK'; successfully dropped it, and the procedure never ran the command at the end to re-add it. This is what made me think I needed the commits, but even without them, it still will not complete the whole procedure.
To prove that the procedure DOES run, if given proper data, run this after creating the table, but before creating/running the stored procedure:
INSERT INTO TESTING (TEST_ID, TEST_TYPE)
VALUES ('1', 'hi');
And if you run the proc from a new table (not one with its constraint dropped), it will run fine.
Since mathguy didn't post this as the answer, though I'll credit him for the information...
Answer to why I can't see the duplicates is because the COMMIT does not occur in the procedure when it failed due to a datatype mismatch (which we found was actually in the application's code that sent the variable's values into this procedure, not in the stored procedure, itself). (It's also why I'll mark down anyone that says you don't have to add so many COMMIT lines in this procedure.) The commands were run in the session of the user that starts it - in my case, another session of the same DB user I was logged in with, but started from my application, instead of my SQL Developer session. It also explains why I could do a COMMIT, myself, but it did not affect the application's session - I could not commit any actions ran from another session. Had I ran a COMMIT as an OracleCommand and did an .ExecuteNonQuery on my OracleConnection right after the failure within the catch of my application, I would have seen the rows in SQL Developer without having to do a special query.
So, in short, the only way to see the items was with a direct query using WHERE ID =, find the last ID and increment it, and put it in the query.
This question already has answers here:
Using sequential values for the primary key in an INSERT query
(2 answers)
Closed 9 years ago.
I am trying to load a column with unique sequence number each time a row of data is insrerted in the table.How can this be achieved?
You can create a Sequence, and then use the sequence nextval in your insert statements for the column which you want to have sequential incremented value.
CREATE SEQUENCE seq
INCREMENT BY 1
START WITH 1
NOMAXVALUE
NOCYCLE
CACHE 10;
INSERT INTO tab VALUES (seq.nextval, col1, col2, col3);
there is nothing like "auto_increment" or "identity" in Oracle,
but if you want auto increment in your column value you can use Sequence for the this.
after creating sequence you can use After Insert Trigger to insert identical value.
here is trigger example...
CREATE OR REPLACE TRIGGER dep_ins_trig
BEFORE INSERT ON <table_name>
FOR EACH ROW
BEGIN
SELECT dept_seq.NEXTVAL
INTO :new.id
FROM dual;
END;
/
This is achieved by Trigger and Sequence when you want serialized number that anyone can easily read/remember/understand. But if you don't want to manage ID Column (like emp_id) by this way, and value of this column is not much considerable, you can use SYS_GUID() at Table Creation to get Auto Increment like this.
CREATE TABLE <table_name>
(emp_id RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
name VARCHAR2(30));
Now your emp_id column will accept "globally unique identifier value".
you can insert value in table by ignoring emp_id column like this.
INSERT INTO <table_name> (name) VALUES ('name value');
So, it will insert unique value to your emp_id Column.
I have table with two rows which one ID with auto increment and there are much row last number ID is 89. And then I truncate data/row in the table. And then I insert row again.
But number ID from 90 not from 1 (one). If in mysql if I truncate data in table auto increment start from 1 (one) again. So how in oracle I want to ID autoincrement from one again. Thanx.
Below step when I create table:
// create table;
CREATE TABLE tes (
id NUMBER NULL,
ip_address varchar2(25) NOT NULL
PRIMARY KEY (id)
);
// and create increment;
CREATE SEQUENCE tes_sequence START WITH 1 INCREMENT BY 1;
// and create trigger;
CREATE OR REPLACE TRIGGER tes_trigger
BEFORE INSERT
ON tes
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT tes_sequence.nextval INTO :NEW.ID FROM dual;
END;
Oracle sequence is a separate object and is not connected with table. If you need to start sequence after truncating a table you need to alter the sequence. Have a look here: How do I reset a sequence in Oracle?