Problem in oracle trigger query - sql

Can anyone please tell me what is wrong with this query?
create trigger Test_trigger
before insert on Test for each row
begin select TestSequence.nextval into :new.id from dual;
end;/
When I run this query, I get the following error:
ERROR at line 1: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
;
The symbol ";" was substituted for "end-of-file" to continue.
I am using Oracle 10g Express Edition.

The trailing "/" is SQL*Plus syntax. You're probably using the SQL tool in Oracle Apex - in which case, omit the "/".

It should work if you remove the "/" at the end.

Here is the script I'm trying to execute:
drop index TestTableIdx1;
drop index TestIdx1;
drop index TestIdx2;
drop table Test;
drop sequence TestSequence;
drop table TestTable;
create table TestTable (
objId number NOT NULL,
type varchar(16) NOT NULL,
title varchar(192) ,
url varchar(192) ,
primary key(objId, type)
);
create table Test (
id number NOT NULL,
objId number NOT NULL,
type varchar(16) NOT NULL,
timeslot timestamp NOT NULL,
contextId number ,
pubId number NOT NULL,
category varchar(24),
meta varchar(32),
pageviews number NOT NULL,
aggrLevel number NOT NULL,
primary key(id)
);
create table Dummy (
id int NOT NULL,
primary key(id)
);
create sequence TestSequence
start with 1
increment by 1
nomaxvalue;
create trigger Test_trigger
before insert on Test
for each row
begin
select TestSequence.nextval into :new.id from dual;
end;
/
create index TestTableIdx1 on TestTable (
objId desc, type asc
);
create index TestIdx1 on Test (
timeslot desc, objId desc, type asc
);
create index TestIdx2 on Test (
timeslot desc
);
create index TestIdx3 on Test (
objId desc, type asc
);
create index TestIdx4 on Test (
contextId desc
);

Related

PostgreSQL create table statement: auto insert id

I am using PostgreSQL 14. For tenant system, My script
DROP TABLE IF EXISTS tenant;
CREATE TABLE tenant
(
id smallserial primary key,
company_tax_code character varying(14),
period character varying(16), -- 2021070420220705
created timestamp with time zone
);
DROP TABLE IF EXISTS account_default;
CREATE TABLE account_default
(
id smallint,
ref_type smallint not null,
ref_type_name character varying(256),
voucher_type smallint not null,
column_name character varying(64) not null,
column_caption character varying(128) not null,
filter_condition character varying(1024),
default_value character varying(32),
sort_order smallint,
created timestamp with time zone,
created_by character varying(64),
modified timestamp with time zone,
modified_by character varying(64),
tenant_id smallint,
PRIMARY KEY (id, tenant_id),
CONSTRAINT fk_tenant FOREIGN KEY (tenant_id) REFERENCES tenant (id)
);
I am looking something like
DROP TABLE IF EXISTS account_default;
CREATE TABLE account_default
(
id smallint default value (max_value of account_default.id + 1 where tenant_id = account_default.tenant_id,
ref_type smallint not null,
ref_type_name character varying(256),
voucher_type smallint not null,
column_name character varying(64) not null,
column_caption character varying(128) not null,
filter_condition character varying(1024),
default_value character varying(32),
sort_order smallint,
created timestamp with time zone,
created_by character varying(64),
modified timestamp with time zone,
modified_by character varying(64),
tenant_id smallint,
PRIMARY KEY (id, tenant_id),
CONSTRAINT fk_tenant FOREIGN KEY (tenant_id) REFERENCES tenant (id)
);
Help me
DROP TABLE IF EXISTS account_default;
CREATE TABLE account_default
(
id smallint default value (max_value of account_default.id + 1 where tenant_id = account_default.tenant_id
I need composite key
(table_id, tenant_id)
(1, 1)
(2, 1)
(3, 1)
(1, 2)
(2, 2)
(1, 3)
If insert, I need
(4, 1)
explain
4 = (max (table_id) where tenant_id = 1) + 1;
insert like tirgger or automation at database-side.
demo
changed all the character varying to text data type.
changed small int to bigint data type.
removed some not null constraint.
the cost is figure out the new tenant id in the current table account_default or not.
function and trigger.
CREATE OR REPLACE FUNCTION restart_seq ()
RETURNS TRIGGER
AS $$
BEGIN
RAISE NOTICE 'new.tenant_id: %', NEW.tenant_id;
RAISE NOTICE 'all.tenant_id: %', (
SELECT
array_agg(tenant_id)
FROM
tenant);
RAISE NOTICE 'new.tenant_id in : %', (
SELECT
NEW.tenant_id IN (
SELECT
tenant_id
FROM
tenant));
IF (NEW.tenant_id NOT IN (
SELECT
tenant_id
FROM
account_default)) THEN
NEW.acc_id = 1;
ALTER SEQUENCE account_default_acc_id_seq
RESTART WITH 2;
RAISE NOTICE 'currval(''account_default_acc_id_seq''): %', currval('account_default_acc_id_seq');
END IF;
RETURN new;
END;
$$
LANGUAGE plpgsql;
create or replace trigger trg_reset_the_accid
before insert on account_default
for each row execute procedure restart_seq();

Argument of AND must not return a set when used with BETWEEN in a check constraint

I am encountering the error "argument of AND must not return a set" from the AND in the check constraint of the below table.
CREATE TABLE loan (
id SERIAL PRIMARY KEY,
copy_id INTEGER REFERENCES media_copies (copy_id),
account_id INT REFERENCES account (id),
loan_date DATE NOT NULL,
expiry_date DATE NOT NULL,
return_date DATE,
CONSTRAINT max_student_concurrent_loans CHECK(
CurrentStudentLoansCount() BETWEEN 1 AND 7
)
);
The implementation of CurrentStudentLoansCount() is shown below.
CREATE OR REPLACE FUNCTION CurrentStudentLoansCount()
RETURNS TABLE(accid BIGINT) AS $$
BEGIN
RETURN QUERY
SELECT COUNT(*)
FROM loan
WHERE account_id IN (SELECT id FROM student)
AND return_date IS NULL
GROUP BY account_id;
END
$$ LANGUAGE PLPGSQL;
Why am I running into this error and how can I work around it?
For context, the below figure displays my database schema.
Your function returns a table with multiple rows so you can't use that for a BETWEEN condition. Presumably you just want that value for the account_id of that row of the table (not for all account_ids).
So change the function to return a single value by passing it the account_id. And you also don't need PL/pgSQL for this:
CREATE OR REPLACE FUNCTION currentstudentloanscount(p_account_id integer)
RETURNS bigint
as
$$
SELECT COUNT(*)
FROM loan
WHERE account_id = p_account_id
AND return_date IS NULL;
$$ LANGUAGE sql;
And change your table definition to:
CREATE TABLE loan (
id SERIAL PRIMARY KEY,
copy_id INTEGER REFERENCES media_copies (copy_id),
account_id INT REFERENCES account (id),
loan_date DATE NOT NULL,
expiry_date DATE NOT NULL,
return_date DATE,
CONSTRAINT max_student_concurrent_loans
CHECK(currentstudentloanscount(account_id) BETWEEN 1 AND 7)
);

I got error on column with identity(1,1)?

Sql developer gives an error of:
ORA-00907: missing right parenthesis, for next table :
create table customer (
CUSTOMER_ID number identity (1,1) not null,
CUSTOMER_PHONE char(13) not null
);
Also the 'identity is red underlined, have no idea why
Proper syntax for Oracle 12c and newer:
create table customer (
CUSTOMER_ID NUMBER GENERATED ALWAYS AS IDENTITY,
CUSTOMER_PHONE char(13) not null
);
-- explicit start and increment
create table customer (
CUSTOMER_ID NUMBER GENERATED ALWAYS AS IDENTITY(START WITH 1 INCREMENT BY 1),
CUSTOMER_PHONE char(13) not null
);
db<>fiddle demo

How can this postgresql query return as table?

I am trying to call modules which in specific course but it returns as error: more than one row returned by a subquery used as an expression
Query:
CREATE OR REPLACE FUNCTION course_modules(_courseID integer)
RETURNS SETOF modules AS
$$
BEGIN
RETURN QUERY SELECT * FROM modules WHERE mod_id =(SELECT module_id from coursemodules WHERE course_id = _courseID);
END
$$
LANGUAGE 'plpgsql';
coursemodule table
CREATE TABLE coursemodules(
course_id integer references courses (id) ON DELETE CASCADE,
module_id integer references modules (mod_id) ON DELETE CASCADE
);
Modules Table
CREATE TABLE modules(
documents text NOT NULL,
mod_id serial primary key,
content text NOT NULL,
title varchar(50) NOT NULL
);
Course Table
CREATE TABLE courses(
finishDate Date,
description text NOT NULL,
duration varchar(50) NOT NULL,
startDate Date,
id serial primary key,
courseName varchar(50) NOT NULL
);
There is no restriction in the coursemodule table that a course could only have one module. Because of that the SELECT module_id from coursemodules WHERE course_id = _courseID subquery could return multiple lines.
If you change mod_id = (SELECT module_id from coursemodules WHERE course_id = _courseID)
to
mod_id IN (SELECT module_id from coursemodules WHERE course_id = _courseID).
It should work. Otherwise you have to add constraints to the coursemodule table.
This is a simple SQL syntax error. You're using
WHERE mod_id =
But you may have more than one row returning from the subquery. User IN:
WHERE mod_id IN

What query creates a trigger to generate composite primary key with two fk?

I'm trying to write a command to create a trigger that generates the composite primary key. This pk is in turn based on two fk.
I'll write example tables to be more specific.
(Table I'm working on)
CREATE TABLE DB.MESSAGE (
TEXT CLOB NOT NULL,
SUBJECT VARCHAR2(2000) NOT NULL,
MSG_TYPE NUMBER(1) NOT NULL,
MAIL_ID NUMBER(10) NOT NULL
)
;
ALTER TABLE DB.MESSAGE ADD CONSTRAINT MSG_PK PRIMARY KEY ( MSG_TYPE, MAIL_ID ) ;
ALTER TABLE DB.MESSAGE ADD
(
CONSTRAINT MESSAGE_TYPE_ID_FK
FOREIGN KEY ( MSG_TYPE )
REFERENCES DB.TYPES ( TYPE_ID )
);
ALTER TABLE DB.MESSAGE ADD
(
CONSTRAINT MESSAGE_MAIL_FK
FOREIGN KEY ( MAIL_ID )
REFERENCES DB.EML_MAIL ( MAILTO_ID )
);
(Referenced tables)
CREATE TABLE DB.TYPES (
TYPE_ID NUMBER(13) NOT NULL,
NAME VARCHAR2(10) NOT NULL
)
;
CREATE TABLE DB.MAIL (
MAIL_ID NUMBER(10) NOT NULL,
MAIL VARCHAR2(350) NOT NULL
)
;
My query so far
create or replace
TRIGGER DB.TRG_MESSAGE_ID
BEFORE INSERT ON DB.MESSAGE
FOR EACH ROW
BEGIN
IF INSERTING THEN
IF :NEW."MSG_ID" IS NULL THEN
SELECT DB.TYPES.TYPE_ID ??????
INTO :NEW."MSG_ID" FROM dual;
END IF;
END IF;
END;
EDIT: So the thinking behind this question was that there would be a separated column with a concatenations of both keys that compose the composite key.
A friend told me this is wrong, you just put both fields as pk and that's that. Is this true?