SQL Trigger throws error but still inserts - sql

I am working on a trigger that is supposed to block an insert when #verkoperstatus is 0; this does function, but for some reason it also stops the insert when #verkoperstatus is 1. What could be the root cause behind this?
CREATE TRIGGER [dbo].[verkoper_check] ON [dbo].[Verkoper]
FOR INSERT,UPDATE
AS
BEGIN
DECLARE #verkoperstatus bit
DECLARE #gebruikersnaam varchar(25)
SELECT #gebruikersnaam = gebruikersnaam FROM inserted
SELECT #verkoperstatus = verkoper FROM Gebruiker WHERE gebruikersnaam = #gebruikersnaam
IF #verkoperstatus = 0
BEGIN
RAISERROR('Geen verkoper!',18,1);
ROLLBACK;
END
ELSE
BEGIN
COMMIT;
END
END
It should insert when #verkoperstatus is 1, and raise an error when #verkopstatus is 0.
The table Gebruiker is references, which includes a 'gebruikersnaam' and a 'verkoper' column. The value of the 'gebruikersnaam' column is the identifying column which (in this specific case is 'Lars'). Verkoper is a bit column, which indicated if one is a seller or not, so this has the value of a 0 or a 1.
The goal I am trying to achieve is to have an insert on the Verkoper tabel if a 'gebruikersnaam' has the 'verkoper' value of one.
This means if there is a row in Gebruiker with the 'gebruikersnaam' of Lars and the verkoper has a value of 1. This will be an allowed insert into the Verkoper tabel.
As the Verkoper has the following columns: 'gebruikersnaam', 'banknaam', 'rekeningnummer', 'controleoptienaam' and 'creditcardnummer'. When 'gebruikersnaam' corresponds with a 'gebruikersnaam' from the Gebruikers table AND has a value of 1 in the 'verkoper' column this record will be allowed to be inserted into the Verkoper table.
As of now there is a row in the Gebruikers column which includes the gebruikersnaam 'Lars' and a verkoper value of '1'. Meaning any SQL Insert with the gebruikersnaam of 'Lars' should be allowed into the Verkoper table.
This however does not function the way I believe it should.
These are the tables mentioned above:
CREATE TABLE Verkoper (
gebruikersnaam varchar(25) NOT NULL,
banknaam varchar(255) NULL,
rekeningnummer varchar(32) NULL,
controleoptienaam char(10) NOT NULL,
creditcardnummer integer NULL,
CONSTRAINT pk_Verkoper PRIMARY KEY (gebruikersnaam),
CONSTRAINT fk_Verkoper_Gebruikersnaam FOREIGN KEY (gebruikersnaam) REFERENCES Gebruiker(gebruikersnaam),
CONSTRAINT ck_rekening CHECK (rekeningnummer is NOT NULL OR creditcardnummer is NOT NULL),
CONSTRAINT ck_controleoptie CHECK (controleoptienaam IN('Post', 'Creditcard'))
)
CREATE TABLE Gebruiker(
gebruikersnaam varchar(25) NOT NULL,
voornaam varchar(25) NOT NULL,
achternaam varchar(25) NOT NULL,
adresregel_1 varchar(255) NULL,
adresregel_2 varchar(255) NULL,
postcode char(7) NULL,
plaatsnaam varchar(255) NULL,
land varchar(255) NULL,
geboortedag char(10) NOT NULL,
mailbox varchar(255) NOT NULL,
wachtwoord varchar(255) NOT NULL,
verkoper bit NOT NULL,
CONSTRAINT pk_gebruiker PRIMARY KEY (gebruikersnaam),
)
For the inserts I am using the following data:
INSERT INTO Gebruiker VALUES ('Lars', 'Lars', 'Last_name', null, null, null, null, null, '04/04/2019', 'lars#mymailbox.cloud', 'MyPassword', 1)
INSERT INTO Verkoper VALUES ('Lars', 'ING', 'NL32ABN32492809', 'Post', null)

This is untested, however, I suspect this is the logic you really need:
CREATE TRIGGER [dbo].[verkoper_check] ON [dbo].[Verkoper]
FOR INSERT,UPDATE
AS BEGIN
IF EXISTS(SELECT 1
FROM inserted i
JOIN Gebruiker G ON i.gebruikersnaam = G.gebruikersnaam
WHERE G.verkoper = 0) BEGIN
RAISERROR('Geen verkoper!',18,1);
ROLLBACK;
END;
END;

Related

Unable to create trigger in PhpMyAdmin

Happy Thanksgiving!
I am trying to create a trigger phpmyadmin to update a salary amount.
I made the following table:
CREATE TABLE `salaryraise` (
`SalaryChangeID` decimal(12,0) NOT NULL,
`OldRate` decimal(8,2) NOT NULL,
`NewRate` decimal(8,2) NOT NULL,
`TeacherID` decimal(12,0) NOT NULL,
`ChangeDate` date NOT NULL
)
And I have my existing teacher_data Table
CREATE TABLE `teacherdata` (
`teacher_data_id` int(12) NOT NULL,
`gender` varchar(12) NOT NULL,
`race` varchar(12) NOT NULL,
`hire_date` date NOT NULL,
`salary` decimal(8,2) NOT NULL,
`certicationValid` varchar(12) NOT NULL,
`subjectTaught` varchar(32) NOT NULL
)
And I am trying to run my trigger
CREATE TRIGGER SalaryRaise
On Teacher
AFTER UPDATE
AS
BEGIN
DECLARE #OldRate DECIMAL(8,2) = (SELECT Rate FROM DELETED);
DECLARE #NewRate DECIMAL(8,2) = (SELECT Rate FROM INSERTED);
IF (#OldRate <> #NewRate)
INSERT INTO salaryraise(SalaryRaiseID, OldRate, NewRate, teacher_id, ChangeDate)
VALUES (ISNULL((SELECT MAX(SalaryRaiseID)+1 FROM SalaryRaise),1),
#OldRate,
#NewRate,
(SELECT teacher_id FROM INSERTED),
GETDATE());
END;
I get the following error in PHPMYADMIN
CREATE TRIGGER SalaryRaise
On Teacher
AFTER UPDATE
AS
BEGIN
DECLARE #OldRate DECIMAL(8,2) = (SELECT Rate FROM DELETED);
MySQL said: Documentation
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'On Teacher
AFTER UPDATE
AS
BEGIN
DECLARE #OldRate DECIMAL(8,2) = (SELECT...' at line 2
Please Advise

Postgres update a diferent table

Hello im trying to create a trigger, after insert on a certain column on a certain row the trgigger adds the that value on the other table on a certain place.
I have a table called updates:
create table public.updates (
id serial not null,
matricula varchar(10) NOT NULL,
primensalidade int,
segmensalidade int,
tercmensalidade int,
quamensalidade int,
quimensalidade int,
sexmensalidade int,
foreign key (id) references creditos(id));
And i have a table called:
CREATE TABLE public.creditos (
id serial NOT NULL,
veiculo varchar(10) NOT NULL,
matricula varchar(10) NOT NULL,
nome bpchar(30) NOT NULL,
telemovel varchar(10) NOT NULL,
valordevendapronto int4 NOT NULL,
juros int4 NULL,
valortotal int4 NULL,
entradainicial int4 NOT NULL,
primensalidade int4 NULL,
segmensalidade int4 NULL,
tercmensalidade int4 NULL,
quamensalidade int4 NULL,
quimensalidade int4 NULL,
sexmensalidade int4 NULL,
datainicial date NULL DEFAULT now(),
datafinal date NULL,
pago bpchar(3) NULL,
CONSTRAINT creditos_pkey PRIMARY KEY (id));
And my objective is after i insert on updates.primensalidade, it goes to creditos.primensalidade and change it to what i choosed before on updates.primensalidade where my creditos.matricula and updates.matricula are the same.
what i have soo far is:
CREATE OR REPLACE function creditoupdate()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
begin
insert into creditos(primensalidade) values(new.primensalidade) where matricula = new.matricula ;
return new;
end;
$function$
;
create trigger creditoupdatetrigger after
insert
on
updates for each row execute function creditoupdate();
I hope you can help me thx.
WHERE cannot be used in INSERT like that.
To to update primensalidade column in table creditos, the following can be used:
UPDATE creditos SET primensalidade = new.primensalidade where matricula = new.matricula;
More about UPDATE - https://www.postgresql.org/docs/current/sql-update.html
More about INSERT - https://www.postgresql.org/docs/current/sql-insert.html

Trouble using an equal sign in SQL trigger

This is my table:
CREATE TABLE [dbo].[tblVisitors] (
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[IP] NVARCHAR (100) NOT NULL,
[ProfileId] INT NULL,
[DateVisit] DATE NOT NULL,
[TimeVisit] TIME (0) NOT NULL,
[Browser] NVARCHAR (50) NOT NULL,
[UserOS] NVARCHAR (500) NOT NULL,
CONSTRAINT [PK_tblVisitors] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_tblVisitors_tblProfile] FOREIGN KEY ([ProfileId]) REFERENCES [dbo].[tblProfile] ([Id]) ON DELETE SET NULL
);
I wrote a trigger to avoid redundancy:
CREATE TRIGGER [dbo].[Trigger_tblVisitors_OnInsert]
ON [dbo].[tblVisitors]
INSTEAD OF INSERT
AS
BEGIN
SET NoCount ON;
DECLARE #C INT;
SELECT *
INTO #TEMP
FROM inserted A
WHERE
NOT EXISTS (SELECT *
FROM tblVisitors B
WHERE (A.IP = B.IP)
AND (A.DateVisit = B.DateVisit)
AND (A.ProfileId = B.ProfileId));
IF (SELECT COUNT(*) FROM #TEMP) = 0
BEGIN
PRINT 'DUPLICATE RECORD DETECTED';
ROLLBACK TRANSACTION;
RETURN;
END
INSERT INTO tblVisitors (IP, ProfileId, DateVisit, TimeVisit, Browser, UserOS)
SELECT IP, ProfileId, DateVisit, TimeVisit, Browser, UserOS
FROM #TEMP;
END
But as this part of the code does not work, redundancy occurs:
(A.ProfileId = B.ProfileId)
Because after deleting this section, the operation is performed correctly. But this condition must be checked.
Using my psychic skills, I suspect that you have ProfileId values that are null, and in SQL the expression null = null is not true, but your logic requires it to be true.
Try this:
AND (A.ProfileId = B.ProfileId OR (A.ProfileId IS NULL AND B.ProfileId IS NULL))

How to save auto generated primary key Id in foreign key column in same table

Following is the table structure:
CREATE TABLE [User] (
[Id] bigint identity(1,1) not null,
[FirstName] nvarchar(100) not null,
[LastName] nvarchar(100) not null,
[Title] nvarchar(5) null,
[UserName] nvarchar(100) not null,
[Password] nvarchar(100) not null,
[Inactive] bit null,
[Created] Datetime not null,
[Creator] bigint not null,
[Modified] DateTime null,
[Modifier] bigint null
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] Asc
)
);
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]'))
ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id])
GO
INSERT INTO [User] (Creator) Values ([Id] ?)
This is a case when table is empty and first user is going to add in table. Otherwise I don't have issue.
How can I insert Id in creator column with insert statement at the same time?
One way could be using Sequence instead of identity column. The below script might serve the same purpose:
CREATE SEQUENCE dbo.useridsequence
AS int
START WITH 1
INCREMENT BY 1 ;
GO
CREATE TABLE [User] (
[Id] bigint DEFAULT (NEXT VALUE FOR dbo.useridsequence) ,
[FirstName] nvarchar(100) not null,
[LastName] nvarchar(100) not null,
[Title] nvarchar(5) null,
[UserName] nvarchar(100) not null,
[Password] nvarchar(100) not null,
[Inactive] bit null,
[Created] Datetime not null,
[Creator] bigint DEFAULT NEXT VALUE FOR dbo.useridsequence ,
[Modified] DateTime null,
[Modifier] bigint null
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED
(
[Id] Asc
)
);
IF NOT EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id = OBJECT_ID(N'[FK_User_Creator]') AND parent_object_id = OBJECT_ID(N'[User]'))
ALTER TABLE [User] ADD CONSTRAINT [FK_User_Creator] FOREIGN KEY([Creator]) REFERENCES [User]([Id])
GO
INSERT INTO [User]
(
-- Id -- this column value is auto-generated
FirstName,
LastName,
Title,
UserName,
[Password],
Inactive,
Created,
Creator,
Modified,
Modifier
)
VALUES
(
'Foo',
'Bar',
'Title',
'UserName ',
'Password',
0,
GETDATE(),
DEFAULT,
GETDATE(),
1
)
SELECT * FROM [User] AS u
Result :
The short answer is that you can't do this. And I suggest your model is logically flawed in the first place. Do you intend to define all actual database users (e.g., create user ... for login ...) as rows in [Users]? You need to think about that - but the typical answer is no. If the answer is yes, then you don't need the creator column at all because it is redundant. All you need is the created date - for which you probably should have defined a default.
But if you want to do this, you will need to do it in two steps (and you will need to make the column nullable). You insert a row (or rows) with values for the "real" data columns. Then update those same rows with the identity values generated for id. An example showing different ways to do this
use tempdb;
set nocount on;
CREATE TABLE dbo.[user] (
[user_id] smallint identity(3,10) not null primary key,
[name] nvarchar(20) not null,
[active] bit not null default (1),
[created] Datetime not null default (current_timestamp),
[creator] smallint null
);
ALTER TABLE dbo.[user] ADD CONSTRAINT [fk_user] FOREIGN KEY(creator) REFERENCES dbo.[user](user_id);
GO
-- add first row
insert dbo.[user] (name) values ('test');
update dbo.[user] set creator = SCOPE_IDENTITY() where user_id = SCOPE_IDENTITY()
-- add two more rows
declare #ids table (user_id smallint not null);
insert dbo.[user] (name) output inserted.user_id into #ids
values ('nerk'), ('pom');
update t1 set creator = t1.user_id
from #ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id;
select * from dbo.[user] order by user_id;
-- mess things up a bit
delete dbo.[user] where name = 'pom';
-- create an error, consume an identity value
insert dbo.[user](name) values (null);
-- add 2 morerows
delete #ids;
insert dbo.[user] (name) output inserted.user_id into #ids
values ('nerk'), ('pom');
update t1 set creator = t1.user_id
from #ids as newrows inner join dbo.[user] as t1 on newrows.user_id = t1.user_id;
select * from dbo.[user] order by user_id;
drop table dbo.[user];
And I changed the identity specification to demonstrate something few developers realize. It isn't always defined as (1,1) and the next inserted value can jump for many reasons - errors and caching/restarts for example. Lastly, I think you will regret naming a table with a reserved word since references to it will require the use of delimiters. Reduce the pain.

trigger in sql problem

this is my trigger
ALTER trigger [dbo].[addpay]
on [dbo].[pays]
after insert
as
declare #idtutor int
set #idtutor =(select idtutor from inserted)
begin
insert into pays (idtutor,nopay,datex,paythismonth)values (#idtutor,600,GETDATE(),'no')
end
but it doesn't add a new pays after inserted a tutor... i dont watch any bug, mistake, why doesn't it work
my tables
create table Tutor
(
[IdTutor] int primary key identity not null,
[Nombre] varchar(150) not null,
[ApellidoPaterno] varchar (150) not null,
[ApellidoMaterno] varchar (150) not null,
[EstadoCivil] varchar (10) not null,
[FechaNacimiento] varchar(50),
[Municipio] varchar(150) not null,
[Estado] varchar(150) not null,
[Direccion] varchar(250) not null,
[Sexo] varchar (9) not null,
[TelefonoTutor] char(10) not null,
[CelularTutor] char(15) not null,
[EmailTutor] char(50) not null,
[Empresa] varchar(150) not null,
[Ocupacion] varchar(250) not null,
[DireccionEmpresa] varchar (250) not null,
[TelefonoEmpresa] char(10) not null,
[CelularEmpresa] char(15) not null,
[EmailEmpresa] varchar(50) not null
)
create table pays
(
idpay int primary key not null identity,
idtutor int not null,
nopay float,
datex datetime,
paythismonth varchar(2)
)
You need to create the trigger on the table for where you want it to fire when a new record is inserted (Tutor in this case).
Additionally you need to remember that inserts/update statements can affect multiple rows so assigning to scalar variables won't work. The trigger you need is
CREATE TRIGGER YourTrigger
ON [dbo].[Tutor]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
INSERT INTO pays
(idtutor,
nopay,
datex,
paythismonth)
SELECT idtutor,
600,
GETDATE(),
'no'
FROM inserted
END
You will also need to drop the other trigger in your question with DROP TRIGGER [dbo].[addpay]