please assist in executing the procedure [closed] - tsql

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Could you please assist in executing this procedure please .
Canot execute this procedure ,
however procedure run successfully without errors
exec iso.proc_Additem('12345')
And
**Canot insert values**
insert into tbl_Handle
values(SYSTEM_USER,DATE)
sql stored procedure is
--Procedure Add item to the list --
Create procedure iso.proc_Additem
#card_id nvarchar(50) ,
#card_type nvarchar(1) = 'N'
AS
BEGIN
Begin transaction
Insert into iisr.tbl_handle
( UserName )
Values
( system_user )
-Comented --Table definition create table iso.tbl_Handle
( Handle int identity(1,1)
, UserName nvarchar(50)
, Created date
, constraint pk_Handle primary key(Handle)
);--
/* Get Handle */
declare #Card_Handle int
SELECT #Card_Handle = SCOPE_IDENTITY() -- get handle
Insert into iso.tbl_card_list
( Card_ID , card_type )
Values
(#Card_ID,#Card_Type)
-comented --table definition iso.tbl_card_list
CREATE TABLE iso.tbl_card_list
( Card_Handle int
, Card_ID nvarchar(50) not null
, Card_Type char(1) Default 'N' not null
, Delete_handle int not null
, Constraint PK_Card_List Primary Key ( Card_Handle)
, Constraint FK_1 foreign key (Card_Handle) references iso.tbl_Handle (Handle)
, Constraint FK_2 foreign key(delete_Handle)references iso.tbl_Handle(Handle)
, Constraint CK_1 check (Card_Type in ('N','T')));--
Commit transaction
End

Remove the parenthesis. You call the SP like this.
exec iso.proc_Additem '12345', 'n'

Related

Insert record dynamically inside of Procedural Trigger

We are looking to convert our database over to Postgres (9.3.5), which I have no experience with, and I am trying to get our audit tables up and running. I understand that each table will need its own trigger, but all triggers can call a single function.
The trigger on the table is passing a list of the columns that need to be audited since some of our columns are not tracked.
Here are some of the posts I followed:
- https://stackoverflow.com/a/7915100/229897
- http://www.postgresql.org/docs/9.3/static/plpgsql-statements.html
- http://www.postgresql.org/docs/9.4/static/plpgsql-trigger.html
When I run this I get the error: ERROR: syntax error at or near "$1"
DROP TABLE IF EXISTS people;
DROP TABLE IF EXISTS a_people;
CREATE TABLE IF NOT EXISTS people (
record_id SERIAL PRIMARY KEY NOT NULL,
first_name VARCHAR NOT NULL,
last_name VARCHAR NOT NULL,
last_updated_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS a_people (
record_id SERIAL PRIMARY KEY NOT NULL,
a_record_id INT,
first_name VARCHAR NULL,
last_name VARCHAR NULL,
last_updated_on TIMESTAMP
);
/******************************************************/
--the function
CREATE OR REPLACE FUNCTION audit_func()
RETURNS TRIGGER AS
$BODY$
DECLARE
audit TEXT := TG_TABLE_SCHEMA || '.a_' || TG_TABLE_NAME;
cols TEXT := TG_ARGV[0];
BEGIN
EXECUTE format('INSERT INTO %1$s(a_%2$s) SELECT %2$s FROM ($1)', audit, cols) USING OLD;
NEW.last_updated_on = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql;
/******************************************************/
--the trigger calling the function to update inbound records
CREATE TRIGGER build_user_full_name_trg
BEFORE UPDATE
ON people
FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE PROCEDURE audit_func('record_id,first_name,last_name');
/******************************************************/
INSERT INTO people (first_name, last_name) VALUES ('George','Lincoln');
UPDATE people SET last_name = 'Washington' WHERE first_name = 'George';
SELECT * FROM people;
I welcome your assistance (and patience)!
This subselect should work:
EXECUTE format('INSERT INTO %1$s(a_%2$s) SELECT %2$s FROM (select ($1).*) XX', audit, cols) USING OLD;

CONSTRAINT to check values from a remotely related table (via join etc.)

I would like to add a constraint that will check values from related table.
I have 3 tables:
CREATE TABLE somethink_usr_rel (
user_id BIGINT NOT NULL,
stomethink_id BIGINT NOT NULL
);
CREATE TABLE usr (
id BIGINT NOT NULL,
role_id BIGINT NOT NULL
);
CREATE TABLE role (
id BIGINT NOT NULL,
type BIGINT NOT NULL
);
(If you want me to put constraint with FK let me know.)
I want to add a constraint to somethink_usr_rel that checks type in role ("two tables away"), e.g.:
ALTER TABLE somethink_usr_rel
ADD CONSTRAINT CH_sm_usr_type_check
CHECK (usr.role.type = 'SOME_ENUM');
I tried to do this with JOINs but didn't succeed. Any idea how to achieve it?
CHECK constraints cannot currently reference other tables. The manual:
Currently, CHECK expressions cannot contain subqueries nor refer to
variables other than columns of the current row.
One way is to use a trigger like demonstrated by #Wolph.
A clean solution without triggers: add redundant columns and include them in FOREIGN KEY constraints, which are the first choice to enforce referential integrity. Related answer on dba.SE with detailed instructions:
Enforcing constraints “two tables away”
Another option would be to "fake" an IMMUTABLE function doing the check and use that in a CHECK constraint. Postgres will allow this, but be aware of possible caveats. Best make that a NOT VALID constraint. See:
Disable all constraints and table checks while restoring a dump
A CHECK constraint is not an option if you need joins. You can create a trigger which raises an error instead.
Have a look at this example: http://www.postgresql.org/docs/9.1/static/plpgsql-trigger.html#PLPGSQL-TRIGGER-EXAMPLE
CREATE TABLE emp (
empname text,
salary integer,
last_date timestamp,
last_user text
);
CREATE FUNCTION emp_stamp() RETURNS trigger AS $emp_stamp$
BEGIN
-- Check that empname and salary are given
IF NEW.empname IS NULL THEN
RAISE EXCEPTION 'empname cannot be null';
END IF;
IF NEW.salary IS NULL THEN
RAISE EXCEPTION '% cannot have null salary', NEW.empname;
END IF;
-- Who works for us when she must pay for it?
IF NEW.salary < 0 THEN
RAISE EXCEPTION '% cannot have a negative salary', NEW.empname;
END IF;
-- Remember who changed the payroll when
NEW.last_date := current_timestamp;
NEW.last_user := current_user;
RETURN NEW;
END;
$emp_stamp$ LANGUAGE plpgsql;
CREATE TRIGGER emp_stamp BEFORE INSERT OR UPDATE ON emp
FOR EACH ROW EXECUTE PROCEDURE emp_stamp();
...i did it so (nazwa=user name, firma = company name) :
CREATE TABLE users
(
id bigserial CONSTRAINT firstkey PRIMARY KEY,
nazwa character varying(20),
firma character varying(50)
);
CREATE TABLE test
(
id bigserial CONSTRAINT firstkey PRIMARY KEY,
firma character varying(50),
towar character varying(20),
nazwisko character varying(20)
);
ALTER TABLE public.test ENABLE ROW LEVEL SECURITY;
CREATE OR REPLACE FUNCTION whoIAM3() RETURNS varchar(50) as $$
declare
result varchar(50);
BEGIN
select into result users.firma from users where users.nazwa = current_user;
return result;
END;
$$ LANGUAGE plpgsql;
CREATE POLICY user_policy ON public.test
USING (firma = whoIAM3());
CREATE FUNCTION test_trigger_function()
RETURNS trigger AS $$
BEGIN
NEW.firma:=whoIam3();
return NEW;
END
$$ LANGUAGE 'plpgsql'
CREATE TRIGGER test_trigger_insert BEFORE INSERT ON test FOR EACH ROW EXECUTE PROCEDURE test_trigger_function();

how to create a column constant in Postgresql

create table test(
t_id SERIAL primary key,
t_date CONSTANT date default CURRENT_DATE
);
ERROR: syntax error at or near "date"
LINE 3: t_date CONSTANT date default CURRENT_DATE
^
********** Error **********
ERROR: syntax error at or near "date"
SQL state: 42601
For a default value you can use a function,
CREATE TABLE test(
t_id SERIAL primary key,
t_date date DEFAULT now()
);
about constant, I never used, even other SQL (!), only in a PL/SQL context ...
If you need a "no update" constraint, you can use a trigger. Example:
CREATE FUNCTION correct_update() RETURNS trigger AS $$
BEGIN
NEW.t_date=OLD.t_date;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER no_date_update
BEFORE BEFORE UPDATE ON test
FOR EACH ROW
WHEN (OLD.t_date IS DISTINCT FROM NEW.t_date)
EXECUTE PROCEDURE correct_update();
For a complete control, you need also trigg the INSERT event, (and does not need a default value anymore because insert trigger will do):
create table test(
t_id SERIAL primary key,
t_date date -- a default will be redundant
);
CREATE FUNCTION correct_date() RETURNS trigger AS $$
BEGIN
IF TG_OP = 'INSERT' THEN
NEW.t_date=now(); -- default value
ELSIF TG_OP = 'UPDATE' THEN -- optional AND OLD.t_date != NEW.t_date
NEW.t_date=OLD.t_date; -- "constant" behaviour
END IF;
RETURN NEW;
END
$$ LANGUAGE plpgsql;
CREATE TRIGGER constant_date
BEFORE INSERT OR UPDATE ON test
FOR EACH ROW
EXECUTE PROCEDURE correct_date();
The OLD.t_date != NEW.t_date comparison is optional, because not affects performance... But is a good practice to use it. Another way is to check in the trigger, by WHEN, but only update triggers can use OLD... So, the best create-triggers for the same correct_date() function (with no old/new comparison) are:
CREATE TRIGGER constant_date_ins
BEFORE INSERT ON test
FOR EACH ROW
EXECUTE PROCEDURE correct_date();
CREATE TRIGGER constant_date_upd
BEFORE UPDATE ON test
FOR EACH ROW
WHEN (OLD.t_date IS DISTINCT FROM NEW.t_date)
EXECUTE PROCEDURE correct_date();
Contextualizing in a scenario
As commented above in the question, there are a lack of contextualization , ex. explaining "why you think this should work and what it should do".
Scenario-1: the db-master need to block careless programmers
We can imagine a framework like CakePHP with a "created" field and a database-master that wants that this field have a "constant behaviour", preventing that careless programmers affects this "expected constraint".
That kind of scenario was used in the anwser.
Scenario-2: the project decision is to alert by error
This is the suggestion #IgorRomanchenko ...
... now here as a Wiki, you can EDIT and add new solution/example ...
You want a check constraint
create table test(
t_id SERIAL primary key,
t_date date default CURRENT_DATE check(t_date = current_date)
);
insert into test(t_date) values (default);
INSERT 0 1
insert into test(t_date) values ('2014-01-01');
ERROR: new row for relation "test" violates check constraint "test_t_date_check"
DETAIL: Failing row contains (2, 2014-01-01).
Or may be a foreign key constraint which allows multiple possible values and can be updated without altering the table's schema
create table date_constraint (
date_constraint date primary key
);
insert into date_constraint (date_constraint) values (current_date);
create table test(
t_id SERIAL primary key,
t_date date
default CURRENT_DATE
references date_constraint(date_constraint)
);
insert into test(t_date) values (default);
INSERT 0 1
insert into test(t_date) values ('2014-01-01');
ERROR: insert or update on table "test" violates foreign key constraint "test_t_date_fkey"
DETAIL: Key (t_date)=(2014-01-01) is not present in table "date_constraint".
http://www.postgresql.org/docs/current/static/ddl-constraints.html

postgres check foreign table column

Is it possible to create a check saying:
"in computer_system, check if ram (from ram_table) matches ram_type (from motherboard_table)"
I've been all over google and stackoverflow, and I've read it was 'impossible' to refer to foreign table column in a check ? But is there a work-around, or how is my logic flawed?
Any help is appreciated!
(Edited for relevant code)
create table computer_system(
system_id int primary key,
ram int not null references ram(ram_id),
cpu int not null references cpu(cpu_id),
mb int not null references motherboard(mb_id),
case int not null references computer_case(case_id),
graphics int references gfx(gfx_id)
);
create table motherboard(
mb_id int primary key,
ram_type varchar(10) not null,
socket varchar(10) not null,
form_factor varchar(30) not null,
ob_gfx boolean default(false)
)
create table ram(
ram_id int primary key,
speed int not null,
size int not null,
type varchar(10) not null
)
You cannot do this with a CHECK constraint in PostgreSQL.
(Theoretically PostgreSQL could allow this, but it'd need to create triggers behind the scenes to check the dependent tables, and it doesn't know how to discover and prove the relationships).
You will need to create a BEFORE INSERT OR UPDATE trigger on computer_system. The trigger must run a query that fetches the corresponding rows in ram and motherboard and compares their type values.
Something like the un-tested:
CREATE OR REPLACE FUNCTION ram_type_matches() RETURNS trigger AS $$
DECLARE
mb_ram_type text;
ram_ram_type text;
BEGIN
mb_ram_type := (SELECT type FROM ram WHERE ram_id = NEW.ram)
ram_ram_type := (SELECT ram_type FROM motherboard WHERE mb_id = NEW.mb)
IF mb_ram_type <> ram_ram_type THEN
RAISE EXCEPTION 'Mismatch between motherboard RAM type % and selected module type %', mb_ram_type, ram_ram_type;
END IF;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER ram_type_matches_tg
BEFORE INSERT OR UPDATE ON computer_system
FOR EACH ROW EXECUTE PROCEDURE ram_type_matches();
Strictly you should also create ON UPDATE triggers on motherboard and ram, preventing the type value from changing after record creation.

Trigger in PostgreSQL does not accept default [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I have a table "xxx" with a column "req".
On this column "req" I would like it always to take values ​​automatically generated in the following manner .. column "req" values ​​Ref_0001, after another insert Ref_0002, Ref_0003 .... ...
I try the first solution thx to #Craig Ringer
CREATE SEQUENCE seq_ref;
CREATE TABLE dossier
(
ref TEXT NOT NULL PRIMARY KEY DEFAULT 'ref' || NEXTVAL('seq_ref'),
value TEXT
);
If you want zero-padded numbers, use this:
CREATE SEQUENCE seq_ref;
CREATE TABLE dossier
(
ref TEXT NOT NULL PRIMARY KEY DEFAULT 'ref' || LPAD(NEXTVAL('seq_ref')::TEXT, 10, '0'),
value TEXT
);
This solution it not works fine with my application program on insert new line ..
but with pgAdmin when I try to insert, the column is empty until I refresh the table .. so I try to work with a trigger.
I finally create a trigger in PostgreSQL, to solve my problem. Generating values for column req of
this form Ref00001, Ref0002 ... but it does not change; it does not work; still empty column:
CREATE table test(
id serial primary key,
non varchar(12),
req varchar(12)
);
CREATE OR REPLACE FUNCTION Start_generate() RETURNS trigger AS $emp_stamp$
BEGIN
NEW.req := ('ref'::text || lpad((nextval('seq_refcomposant'::regclass))::text, 6, '0'::text));
return null;
END;
$emp_stamp$ LANGUAGE plpgsql;
CREATE TRIGGER Generate_ref AFTER INSERT ON test
FOR EACH ROW EXECUTE PROCEDURE Start_generate();
I don't know why it does not work ... I Add Default to
NEW.req := DEFAULT ('ref'::text || lpad((nextval('seq_refcomposant'::regclass))::text, 6, '0'::text));
and there is an error on default!
How can I achieve the effect I want?
You need to use a before trigger, and return the row:
CREATE OR REPLACE FUNCTION Start_generate() RETURNS trigger AS $emp_stamp$
BEGIN
NEW.req := ('ref'::text || lpad((nextval('seq_refcomposant'::regclass))::text, 6, '0'::text));
return NEW;
END;
$emp_stamp$ LANGUAGE plpgsql;
CREATE TRIGGER Generate_ref BEFORE INSERT ON test
FOR EACH ROW
WHEN (NEW.req IS NULL)
EXECUTE PROCEDURE Start_generate();