Error in primary key in sqlplus? - sql

I am beginner in sql.I am using sqlplus to run the sql query .I used simple query but it shows an error like "MISSING RIGHT PARENTHESIS".My objective is to create the autoincrement primary key .Can anyone solve the error?Thanks in advance...
create table student(rollno int identity(1,1) primary key,
name varchar(20),marks int);

For Oracle, the rollno column could be defined as NUMBER(0010) and primary key.
Then you would need to add an ON INSERT trigger to populate rollno from a SEQUENCE. There are many samples of triggers and sequences on this site.

In oracle 12 you can use a identity column to automatically fill your ID
CREATE TABLE students
(
"ID" NUMBER GENERATED BY DEFAULT AS IDENTITY MINVALUE 1 MAXVALUE 9999999999
INCREMENT BY 1 START WITH 1 ,
"NAME" VARCHAR2(20),
"MARKS" NUMBER(2,0),
CONSTRAINT PK_STUDENTS PRIMARY KEY (ID) ENABLE
);
/
This creates a table without any triggers needed and automatically fills the id column (of not specified with a value) with the next number up to 99999...
If you're using oracle 11 and below, you need a trigger on insert and assign a value (custom_sequence.nextval) to the id column.
CREATE TABLE students
(
"ID" NUMBER(5,0) not null,
"NAME" VARCHAR2(20),
"MARKS" NUMBER(2,0),
CONSTRAINT PK_STUDENTS PRIMARY KEY (ID) ENABLE
);
/
CREATE SEQUENCE SEQ_STUDENTS INCREMENT BY 1 START WITH 1;
/
TRIGGER TC_students
before insert on students
for each row
begin
if (:new.id is null) then
select SEQ_students.nextval into :new.id from dual;
end if;
end;
/
And please use VARCHAR2.

Related

Postgres breaking null constraint on a serial column

I have a table that I create independently, the primary key is set with the serial type and a sequence applied to the table, but when I try to insert a value a NULL CONSTRAINT error is thrown and the return looks like null was passed, am I missing something in the INSERT statement?
SQL for table generation:
DROP TABLE IF EXISTS public."Team" CASCADE;
CREATE TABLE public."Team" (
"IdTeam" serial PRIMARY KEY,
name text NOT null,
CONSTRAINT "pKeyTeamUnique" UNIQUE ("IdTeam")
);
ALTER TABLE public."Team" OWNER TO postgres;
DROP SEQUENCE IF EXISTS public."Team_IdTeam_seq" CASCADE;
CREATE SEQUENCE public."Team_IdTeam_seq"
AS integer
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
ALTER TABLE public."Team_IdTeam_seq" OWNER TO postgres;
ALTER SEQUENCE public."Team_IdTeam_seq" OWNED BY public."Team"."IdTeam";
SQL for insert :
INSERT INTO public."Team" (name) values ('Manchester Untited');
The returning error:
ERROR: null value in column "IdTeam" violates not-null constraint
DETAIL: Failing row contains (null, Manchester Untited).
SQL state: 23502
I am baffled. Why are you trying to define your own sequence when the column is already defined as serial?
Second, a primary key constraint is already unique. There is no need for a separate unique constraint.
Third, quoting identifiers just makes the code harder to write and to read.
You can just do:
DROP TABLE IF EXISTS public.Team CASCADE;
CREATE TABLE public.Team (
IdTeam serial PRIMARY KEY,
name text NOT null
);
INSERT INTO public.Team (name)
VALUES ('Manchester Untited');
Dropping the sequence causes the default definition for the IdTeam column to be dropped. After recreating the sequence you will have to recreate the default definition.

ORA-00904: "NO_OF_PROJ_PER_CON_PY": invalid identifier

I am trying to create a fact table which will display the number of projects per consultant per year. It has 2 dimension tables 1 for time (report_time_dim) and the other for consultants(consultant_dim) then the main fact table (fact_table).
CREATE TABLE fact_table(
fact_key INTEGER NOT NULL,
consultant_key INTEGER NOT NULL,
time_key INTEGER NOT NULL,
no_of_projects_py INTEGER,
no_of_consultants_py INTEGER,
no_of_accounts_py INTEGER,
no_of_proj_per_con_py INTEGER,
fk1_time_key INTEGER NOT NULL,
fk2_consultant_key INTEGER NOT NULL,
-- Specify the PRIMARY KEY constraint for table "fact_table".
-- This indicates which attribute(s) uniquely identify each row of data.
CONSTRAINT pk_fact_table PRIMARY KEY (consultant_key,time_key)
);
CREATE TABLE report_time_dim(
time_key INTEGER NOT NULL,
year INTEGER,
-- Specify the PRIMARY KEY constraint for table "time_dim".
-- This indicates which attribute(s) uniquely identify each row of data.
CONSTRAINT pk_report_time_dim PRIMARY KEY (time_key)
);
CREATE TABLE consultant_dim(
consultant_key INTEGER NOT NULL,
project_id INTEGER,
consultant_id INTEGER,
-- Specify the PRIMARY KEY constraint for table "consultant_dim".
-- This indicates which attribute(s) uniquely identify each row of data.
CONSTRAINT pk_consultant_dim PRIMARY KEY (consultant_key)
);
Each table has it's own surrogate key and I have managed to populate the time and consultant tables successfully, however the issue I'm having is with the fact table. When I try to populate it I get the error ORA-00904: "NO_OF_PROJ_PER_CON_PY": invalid identifier. I am unsure how I can go about fixing this and populating the fact table so it will display the information I want. Any help would be appreciated.
--populate fact_table
--table that lists consultant ids, project ids and years
DROP TABLE temp_fact1;
CREATE TABLE temp_fact1 AS
SELECT project_id, fk2_consultant_id, to_number(to_char(lds_project.pj_actual_start_date, 'YYYY')) as which_year FROM lds_project;
--display table
SELECT * FROM temp_fact1;
--list that counts the number of projects for each consultant and specify the year
DROP TABLE temp_fact2;
CREATE TABLE temp_fact2 AS
SELECT which_year, fk2_consultant_id, COUNT(*) project_id FROM temp_fact1 GROUP by fk2_consultant_id, which_year;
--display table
SELECT * FROM temp_fact2;
--fact table surrogate key
DROP SEQUENCE fact_seq;
CREATE SEQUENCE fact_seq
START WITH 1
INCREMENT BY 1
MAXVALUE 1000000
MINVALUE 1
NOCACHE
NOCYCLE;
--load data
INSERT INTO fact_table (fact_key, consultant_key, time_key, no_of_proj_per_con_py)
SELECT fact_seq.nextval, consultant_key, report_time_dim.time_key, no_of_proj_per_con_py FROM temp_fact2, report_time_dim WHERE temp_fact2.which_year = report_time_dim.year;
Try just running this select by itself - it's the last line in your script.
SELECT fact_seq.nextval,
consultant_key,
report_time_dim.time_key,
no_of_proj_per_con_py
FROM temp_fact2, report_time_dim
WHERE temp_fact2.which_year = report_time_dim.year;
It doesn't look like either TEMP_FACT2 or REPORT_TIME_DIM has a column named no_of_proj_per_con_py. I'm not sure where you want to pull that data from, actually.

Sequence in Oracle/PostgreSQL with no ID in insert statement

I'm try to create table with clever sequence generator for using this insert-strucure:
insert into SOMEUSERS (SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values ('Artem', 'PracTimPatie');
instead of this:
insert into SOMEUSERS (SOMEUSERS_ID, SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values (2, 'Artem', 'PracTimPatie');
or this structure:
insert into SOMEUSERS (SOMEUSERS_ID, SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values (GEN_ID_SOMEUSERS.nextval, 'Artem', 'PracTimPatie');
When I executing the following sql script:
create sequence gen_id_someUsers START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
CREATE TABLE loc_db.someUsers
( someUsers_id number(10) DEFAULT gen_id_someUsers.NEXTVAL NOT NULL, --because of this row
someUsers_name varchar2(50) NOT NULL,
someUsers_password varchar2(50),
CONSTRAINT someUsers_pk PRIMARY KEY (someUsers_id)
);
the following notice is given to me:
Error report - SQL Error: ORA-00984: column not allowed here
00984. 00000 - "column not allowed here"
For clarity, said that in this case:
...
CREATE TABLE loc_db.someUsers
( someUsers_id number(10) NOT NULL, --correct this row
...
Sequence GEN_ID_SOMEUSERS created.
Table LOC_DB.SOMEUSERS created.
How can I configure comfortable sequence generator?
(in case of PostgreSQL too. If possible with no trigger(as easily as possible)
Oracle 12c introduces Identity columns:
CREATE TABLE SOMEUSERS (
SOMEUSERS_ID NUMBER(10) GENERATED ALWAYS AS IDENTITY
CONSTRAINT SOMEUSERS__SOMEUSERS_ID__PK PRIMARY KEY,
SOMEUSERS_NAME VARCHAR2(50)
CONSTRAINT SOMEUSERS__SOMEUSERS_NAME__NN NOT NULL,
SOMEUSERS_PASSWORD VARCHAR2(50)
);
If you want to do it in earlier versions then you will need a trigger and a sequence:
CREATE TABLE SOMEUSERS (
SOMEUSERS_ID NUMBER(10)
CONSTRAINT SOMEUSERS__SOMEUSERS_ID__PK PRIMARY KEY,
SOMEUSERS_NAME VARCHAR2(50)
CONSTRAINT SOMEUSERS__SOMEUSERS_NAME__NN NOT NULL,
SOMEUSERS_PASSWORD VARCHAR2(50)
);
/
CREATE SEQUENCE gen_id_someUsers START WITH 1 INCREMENT BY 1 NOCACHE NOCYCLE;
/
CREATE OR REPLACE TRIGGER SOMEUSERS__ID__TRG
BEFORE INSERT ON SOMEUSERS
FOR EACH ROW
BEGIN
:new.SOMEUSERS_ID := gen_id_someUsers.NEXTVAL;
END;
/
You can then just do (either with the identity column or the trigger combined with your sequence):
INSERT INTO SOMEUSERS (
SOMEUSERS_NAME,
SOMEUSERS_PASSWORD
) VALUES (
'Name',
'Password'
);
In postgres just use a serial like this:
CREATE TABLE SOMEUSERS (
SOMEUSERS_ID serial NOT NULL,
SOMEUSERS_NAME text,
SOMEUSERS_PASSWORD text
);
Your insert statement is then easy as:
INSERT INTO SOMEUSERS (SOMEUSERS_NAME, SOMEUSERS_PASSWORD)
values ('Artem', 'PracTimPatie');
If you wanna query the sequence you can just query it like any other relation.
Other answers have addressed postgreSQL and Oracle 12c, so I'll address Oracle 11.2 or earlier here.
From the 11.1 SQL Reference Manual:
DEFAULT
The DEFAULT clause lets you specify a value to be assigned to the column if a subsequent INSERT statement omits a value for the column. The datatype of the expression must match the datatype of the column. The column must also be long enough to hold this expression.
The DEFAULT expression can include any SQL function as long as the function does not return a literal argument, a column reference, or a nested function invocation.
Restriction on Default Column Values
A DEFAULT expression cannot contain references to PL/SQL functions or to other columns, the pseudocolumns CURRVAL, NEXTVAL, LEVEL, PRIOR, and ROWNUM, or date constants that are not fully specified.
(Emphasis mine)
So since you can't put sequence.NEXTVAL in as a DEFAULT value you're basically going to have to use a trigger:
CREATE OR REPLACE TRIGGER SOMEUSERS_BI
BEFORE INSERT
ON LOC_DB.SOMEUSERS
FOR EACH ROW
BEGIN
IF :NEW.SOMEUSERS_ID THEN
:NEW.SOMEUSERS_ID := GEN_ID_SOMEUSERS.NEXTVAL;
END IF;
END SOMEUSERS_BI;
In my experience there is no reliable alternative to using a trigger such as this in Oracle 11.2 or earlier.
Best of luck.

SQLPlus AUTO_INCREMENT Error

When I try and run the following command in SQLPlus:
CREATE TABLE Hotel
(hotelNo NUMBER(4) NOT NULL AUTO_INCREMENT,
hotelName VARCHAR(20) NOT NULL,
city VARCHAR(50) NOT NULL,
CONSTRAINT hotelNo_pk PRIMARY KEY (hotelNo));
I get the following error:
(hotelNo NUMBER(4) NOT NULL AUTO_INCREMENT,
*
ERROR at line 2:
ORA-00907: missing right parenthesis
What am I doing wrong?
Many will gripe about this not being a standard feature in Oracle, but when it’s as easy as two more commands after your CREATE TABLE command I can’t see any good reason to use fancy SQL on every insert.
First let’s create a simple table to play with.
SQL> CREATE TABLE test
(id NUMBER PRIMARY KEY,
name VARCHAR2(30));
Table created.
Now we’ll assume we want ID to be an auto increment field. First we need a sequence to grab values from.
SQL> CREATE SEQUENCE test_sequence
START WITH 1
INCREMENT BY 1;
Sequence created.
Now we can use that sequence in a BEFORE INSERT trigger on the table.
CREATE OR REPLACE TRIGGER test_trigger
BEFORE INSERT
ON test
REFERENCING NEW AS NEW
FOR EACH ROW
BEGIN
SELECT test_sequence.nextval INTO :NEW.ID FROM dual;
END;
/
SQL> INSERT INTO test (name) VALUES ('Jon');
1 row created.
SQL> INSERT INTO test (name) VALUES (’Bork’);
1 row created.
SQL> INSERT INTO test (name) VALUES (’Matt’);
1 row created.
SQL> SELECT * FROM test;
ID NAME
———- ——————————
1 Jon
2 Bork
3 Matt
Oracle has no auto_increment, you need to use sequences.
Or - starting with Oracle 12.1 - you can simply have:
CREATE TABLE employee
(
id NUMBER GENERATED by default on null as IDENTITY
....
)

Autoincrement Primary key in Oracle database

I would like to achieve an identity or auto-incrementing value in a column ala SQL Server:
CREATE TABLE RollingStock
(
Id NUMBER IDENTITY(1,1),
Name Varchar2(80) NOT NULL
);
How can this be done?
As Orbman says, the standard way to do it is with a sequence. What most people also do is couple this with an insert trigger. So, when a row is inserted without an ID, the trigger fires to fill out the ID for you from the sequence.
CREATE SEQUENCE SEQ_ROLLINGSTOCK_ID START WITH 1 INCREMENT BY 1 NOCYCLE;
CREATE OR REPLACE TRIGGER BI_ROLLINGSTOCK
BEFORE INSERT ON ROLLINGSTOCK
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
WHEN (NEW.ID IS NULL)
BEGIN
select SEQ_ROLLINGSTOCK_ID.NEXTVAL
INTO :NEW.ID from dual;
END;
This is one of the few cases where it makes sense to use a trigger in Oracle.
If you really don't care what the primary key holds, you can use a RAW type for the primary key column which holds a system-generated guid in binary form.
CREATE TABLE RollingStock
(
ID RAW(16) DEFAULT SYS_GUID() PRIMARY KEY,
NAME VARCHAR2(80 CHAR) NOT NULL
);