SQL - datetime input doesn't take the time - sql

At the moment I got theses pieces of code;
Create:
CREATE TABLE Vlucht(
Vlucht_ID int IDENTITY(1,1),
Lid_ID int,
Vliegtuig_ID int,
VL_Vertrektijd datetime,
VL_Eindtijd datetime,
VL_Type char(1),
Vl_Notitie varchar(max),
CONSTRAINT PK_Vlucht PRIMARY KEY (Vlucht_ID),
CONSTRAINT FK_Vlucht_Ref_Lid FOREIGN KEY (Lid_ID) REFERENCES Lid (Lid_ID) ON UPDATE CASCADE,
CONSTRAINT FK_Vlucht_Ref_Vliegtuig FOREIGN KEY (Vliegtuig_ID) REFERENCES Vliegtuig (Vliegtuig_ID) ON UPDATE CASCADE,
CONSTRAINT CHK_VL_type CHECK (VL_type = 'R' OR VL_type = 'L')
)
go
Insert:
INSERT INTO Vlucht
VALUES (4, 1, '10-04-2018 14:34', '10-04-2018 15:10', 'R', 'Vlucht van Linda'),
(5, 1, '10-04-2018 14:34', '10-04-2018 15:10', 'R', 'Vlucht van Jaap')
Select:
SELECT FORMAT(VL_Vertrektijd, N'MM-dd-yyyy HH:mm'), +
FORMAT(VL_Eindtijd, N'MM-dd-yyyy HH:mm'),
VL_Type, Vl_Notitie, V_Naam, P_Voornaam, P_Achternaam FROM Vlucht vl
INNER JOIN Vliegtuig v
ON v.Vliegtuig_ID = vl.Vliegtuig_ID
INNER JOIN Lid l
ON l.Lid_ID = vl.Lid_ID
INNER JOIN Persoon p
ON p.Persoon_ID = l.Lid_ID
Result:
10-04-2018 00:00
So it does take the date, but it refuses to input the time given. The problem probably lies within some casting of format problems.

Related

record "new" has no field "user_id" postgreSQL

THIS is what i try and error
postgres=# INSERT INTO cs222p_interchange.Ad(ad_id, plan, content, pic_num, item_id, seller_user_id, placed_date)
postgres-# VALUES ('ADT32457', 'Gold', 'New games available!', 1, 'F7E1N', '4Z5VC', '2022-11-06');
ERROR: record "new" has no field "user_id"
CONTEXT: SQL statement "INSERT INTO TargetedAds(ad_id, user_id)
SELECT NEW.ad_id, NEW.user_id WHERE (
SELECT category
FROM cs222p_interchange.item i
JOIN cs222p_interchange.ad a ON i.item_id = a.item_id
WHERE ad_id = NEW.ad_id AND (buyer_user_id = NEW.user_id OR seller_user_id = NEW.user_id) )
LIKE (
SELECT category
FROM cs222p_interchange.User u
JOIN cs222p_interchange.Categories c ON u.user_id = c.user_id
WHERE user_id = NEW.user_id)
ON CONFLICT DO NOTHING"
PL/pgSQL function addad() line 1 at SQL statement
This is the trigger
CREATE FUNCTION AddAd() RETURNS Trigger AS
$$
BEGIN
INSERT INTO TargetedAds(ad_id, user_id)
SELECT NEW.ad_id, NEW.user_id
WHERE (
SELECT *
FROM cs222p_interchange.item i
JOIN cs222p_interchange.ad a ON i.item_id = a.item_id
WHERE ad_id = NEW.ad_id AND (buyer_user_id = NEW.user_id OR seller_user_id = NEW.user_id) )
= (
SELECT category
FROM cs222p_interchange.User u
JOIN cs222p_interchange.Categories c ON u.user_id = c.user_id
WHERE user_id = NEW.user_id)
ON CONFLICT DO NOTHING;
RETURN NEW;
END;
$$
LANGUAGE PLPGSQL;
CREATE TRIGGER TargetedAdsLogger AFTER INSERT ON cs222p_interchange.Ad FOR EACH ROW EXECUTE FUNCTION AddAd();
This is the Table
CREATE TABLE TargetedAds(
ad_id text,
user_id text,
PRIMARY KEY (ad_id, user_id),
FOREIGN KEY (ad_id) REFERENCES cs222p_interchange.Ad
(ad_id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES cs222p_interchange.Seller(user_id) ON DELETE CASCADE
);
This is what i need to insert
INSERT INTO cs222p_interchange.Ad(ad_id, plan, content, pic_num, item_id, seller_user_id, placed_date)
VALUES ('ADT32457', 'Gold', 'New games available!', 1, 'F7E1N', '4Z5VC', '2022-11-06');
This is the definition of the Ad table:
CREATE TABLE cs222p_interchange.Ad(
ad_id text NOT NULL,
plan text NOT NULL ,
content text ,
pic_num int NOT NULL,
item_id text NOT NULL,
seller_user_id text NOT NULL,
placed_date date NOT NULL,
PRIMARY KEY (ad_id),
FOREIGN KEY(item_id) REFERENCES cs222p_interchange.Item(item_id) ON DELETE CASCADE,
FOREIGN KEY(pic_num, item_id) REFERENCES cs222p_interchange.Picture(pic_num, item_id) ON DELETE CASCADE,
FOREIGN KEY(seller_user_id) REFERENCES cs222p_interchange.Seller(user_id) ON DELETE CASCADE
);
I have checked multiple times and all of my tables and columns are existing.

How to create a trigger for this situation?

I have a problem inserting values into a Class table.
I want to write a trigger to prevent happening "an instructor teaches in different class_Id at the same time".
How can I do this?
CREATE TABLE Class
(
Class_ID BIGINT,
c_InstrumentID BIGINT NOT NULL,
c_StudentID BIGINT,
c_InstructorID BIGINT NOT NULL,
c_InstituteId BIGINT NOT NULL,
c_TermSeason NVARCHAR(10),
c_TermYear INT,
c_TimeOfClass TIME NOT NULL,
c_DayOfClass NVARCHAR(30),
c_Eligibility INT,
c_RemainingSession INT,
CONSTRAINT cons_Season
CHECK(c_TermSeason IN ('Spring', 'Summer', 'Fall', 'Winter')),
CONSTRAINT cons_TimeClass
CHECK(c_TimeOfClass BETWEEN '08:30:00' AND '20:30:00'),
CONSTRAINT cons_RemainSession
CHECK (c_RemainingSession BETWEEN 0 AND 12),
FOREIGN KEY(c_InstrumentID)
REFERENCES Instrument(Instrument_ID) ON DELETE NO ACTION,
FOREIGN KEY(c_StudentID)
REFERENCES Student(Student_ID) ON DELETE NO ACTION,
FOREIGN KEY(c_InstructorID)
REFERENCES Instructor(Instructor_ID) ON DELETE NO ACTION,
FOREIGN KEY(c_InstituteId)
REFERENCES Institute(Institute_ID) ON DELETE NO ACTION,
PRIMARY KEY (Class_ID)
)
This is the trigger which I've created:
CREATE OR ALTER TRIGGER One_InstructorDuplicate
ON Class
AFTER INSERT
AS
BEGIN
IF (NOT EXISTS (SELECT *
FROM Class C, ((SELECT * FROM CLASS)
EXCEPT (SELECT * FROM inserted)) AS newC
WHERE newC.c_InstructorID = C.c_InstructorID
AND newC.c_DayOfClass != C.c_DayOfClass
AND newC.c_TermSeason != C.c_TermSeason
AND newC.c_TermYear != C.c_TermYear
AND newC.c_TimeOfClass != C.c_TimeOfClass))
ROLLBACK TRAN
END;
Use inserted and JOIN to the Class table. Check for existence of rows in table that matches your requirement (c_DayOfClass, c_TermSeason etc)
CREATE OR ALTER TRIGGER One_InstructorDuplicate
ON Class
AFTER INSERT
AS
BEGIN
IF EXISTS
(
SELECT *
FROM inserted i
INNER JOIN Class c ON i.c_InstructorID = c.c_InstructorID
WHERE i.Class_ID <> c.Class_ID
AND i.c_DayOfClass = c.c_DayOfClass
AND i.c_TermSeason = c.c_TermSeason
AND i.c_TermYear = c.c_TermYear
AND i.c_TimeOfClass = c.c_TimeOfClass
)
BEGIN
ROLLBACK TRAN
END
END;

Does if statement in after insert trigger matters for the performance in SQL Server? How if statement can be used for value validation?

I'm new to SQL Server, currently taking courses. My question is entirely for educational purposes.
I have an online artshop which includes following tables:
CREATE TABLE artproducts
(
prodid INT PRIMARY KEY IDENTITY (1,1),
catkey INT,
prodname VARCHAR(50) NOT NULL,
unitprice NUMERIC(10,2) NOT NULL,
stocknumbers INT NOT NULL,
available CHAR(3) NOT NULL DEFAULT 'Yes',
FOREIGN KEY(catkey) REFERENCES artcategory(catid)
);
CREATE INDEX idx_name ON artproducts(prodname);
INSERT INTO artproducts(catkey, prodname, unitprice, stocknumbers, available)
VALUES (3, 'Autumn landscape', 150, 2, 'Yes'),
(2, 'Brushes 5 stack', 15.95, 20, 'Yes'),
(2, 'Canvas 100x200', 40.50, 30, 'Yes'),
(1, 'Christmas ornament', 1.95, 30, 'Yes'),
(4, 'Copper carafe from Byzantium', 250.99, 3, 'Yes');
CREATE TABLE artorders
(
orderid INT PRIMARY KEY IDENTITY(1,1),
orderdate DATE NOT NULL,
prodkey INT NOT NULL,
custkey INT NOT NULL,
quantity INT NOT NULL,
orderprice NUMERIC(10,2) NOT NULL,
orderstatus VARCHAR(15) DEFAULT 'In progress',
FOREIGN KEY (prodkey) REFERENCES artproducts (prodid),
FOREIGN KEY (custkey) REFERENCES artcustomers (custid)
);
I created a trigger in SQL Server 2019 to update the price in artorders with the price from artproducts:
ALTER TRIGGER tr_artshop_FIU_checkprice
ON artorders
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE artorders
SET orderprice = prod.unitprice
FROM artproducts AS prod
INNER JOIN inserted AS i ON prod.prodid = i.prodkey
INNER JOIN artorders AS ord ON ord.prodkey = prod.prodid
END;
I tried to do it with if condition - to update the orderprice only when it is different from the one in artproducts. I tried using variables and subqueries, but then the trigger works only for single insert.
ALTER TRIGGER tr_artshop_FIU_checkprice
ON artorders
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
DECLARE #v_price NUMERIC (10,2);
DECLARE #ord_price NUMERIC (10,2);
SET #v_price = (SELECT prod.unitprice FROM artproducts AS prod INNER JOIN inserted AS i ON prod.prodid = i.prodkey)
SET #ord_price = (SELECT ord.orderprice FROM artorders AS ord INNER JOIN inserted AS i ON ord.orderid = i.orderid)
IF #ord_price != #v_price
BEGIN
UPDATE artorders
SET orderprice = prod.unitprice
FROM artproducts AS prod
INNER JOIN inserted AS i
ON prod.prodid = i.prodkey
INNER JOIN artorders AS ord
ON ord.prodkey = prod.prodid
END
END;
So, my question is whether it is better for performance to have if statement, or it doesn't matter?
But if it does, how can I use if condition working for multiple inserts.
Than You very much in advance!!!
It is better for "performance" to not have hidden bugs in your code.
The version with IF is assuming that inserted has only one row. This is a false assumption. In SQL Server, triggers are set-based. This code is broken -- and I really wish SQL Server could find a way to return a syntax error in this case.
Hence, performance has nothing to do with why the first version is better. In practice, I would expect the performance to be better too -- in the cases where the second doesn't generate an error (of the form: scalar subquery returned more than one row).

How to use SELECT in function to compare fields

There are 3 tables: Event, Booking, and Booking_Day.
The idea is that one can book separate days of the event.
I would like to put a constraint on Booking_Day so that Day has to be within Date_Start and Date_End range of the corresponding Event. I decided to use a function that will do this
create table Event
(
Event_ID int identity
constraint Event_pk
primary key nonclustered,
Date_Start date not null,
Date_End date
)
create table Booking
(
Booking_ID int identity
constraint Booking_pk
primary key nonclustered,
Event_ID int not null
constraint Booking_Event_Event_ID_fk
references Event
)
create table Booking_Day
(
Day date not null,
Booking_ID int not null
constraint Booking_Day_Booking_Booking_ID_fk
references Booking,
constraint Booking_Day_pk
primary key nonclustered (Day, Booking_ID)
)
And the function:
CREATE FUNCTION check_if_in_range (
#Event_id int,
#Day DATE
) RETURNS int
BEGIN
declare #result TABLE (Day DATE,Booking_ID INT,Event_ID INT,Date_start DATE, Data_end DATE)
INSERT into #result
SELECT Booking_Day.Day, Booking.Event_ID, Event.Date_Start, Event.Date_End
FROM ((Booking_Day INNER JOIN Booking on Booking_Day.Booking_ID = B.Booking_ID )
INNER JOIN Event on Event.Event_ID = Booking.Event_ID) WHERE Booking_Day.Day = #Day AND B.Event_ID = #Event_id
return ((#Day >= #result.Date_start) AND (#Day <= #result.Data_end))
END
Because of the primary key constraint on Booking_day table, the above should return only one row.
When trying to add function do database I get “[[S0001][137] Must declare the scalar variable “#result".
How do I deal with it? Is my approach entirely wrong and I don’t need a table within the ​function for this?
I don't understand why you would be using a table variable for this. You cannot just refer to a table unless you specify a FROM clause -- you are confusing table variables and scalar variables.
But why bother with variables at all?
IF (EXISTS (SELECT 1
FROM Booking_Day bd INNER JOIN
Booking b
ON bd.Booking_ID = B.Booking_ID INNER JOIN
Event e
ON e.Event_ID = b.Event_ID
WHERE b.Day = #Day AND
b.Event_ID = #Event_id AND
#Day >= e.Date_Start AND
#Day <= e.Data_end
)
)
BEGIN
return 1
END;
return 0

MySQL: select default row (not default values) if other row not available

edit:
I've included the create statements and a small set of test data for you to try out. Therefor, I've changed the example id to 2 in stead of 5 to represent an existing id in the test data.
/ edit
I have three MySQL tables for keeping localized page info:
CREATE TABLE `locale` (
`languageCode` char(3) NOT NULL,
`regionCode` char(3) NOT NULL default 'ZZ',
`isActive` enum('yes','no') NOT NULL default 'no',
PRIMARY KEY (`languageCode`,`regionCode`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `page` (
`id` int(10) unsigned NOT NULL auto_increment,
`parentId` int(10) unsigned default NULL,
PRIMARY KEY (`id`),
KEY `FK_page_page_1` (`parentId`),
CONSTRAINT `FK_page_page_1` FOREIGN KEY (`parentId`) REFERENCES `page` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `pageInfo` (
`pageId` int(10) unsigned NOT NULL,
`languageCode` char(3) NOT NULL,
`regionCode` char(3) NOT NULL default 'ZZ',
PRIMARY KEY (`pageId`,`languageCode`,`regionCode`),
KEY `FK_pageInfo_locale_1` (`languageCode`,`regionCode`),
KEY `FK_pageInfo_page_1` (`pageId`),
CONSTRAINT `FK_pageInfo_locale_1` FOREIGN KEY (`languageCode`, `regionCode`) REFERENCES `locale` (`languageCode`, `regionCode`) ON DELETE CASCADE,
CONSTRAINT `FK_pageInfo_page_1` FOREIGN KEY (`pageId`) REFERENCES `page` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And here is some test data:
/* locale */
INSERT INTO `locale` (languageCode,regionCode,isActive) VALUES ('de','ZZ','yes');
INSERT INTO `locale` (languageCode,regionCode,isActive) VALUES ('en','ZZ','yes');
INSERT INTO `locale` (languageCode,regionCode,isActive) VALUES ('nl','ZZ','yes');
/* page */
INSERT INTO `page` (id,parentId) VALUES (1,NULL);
INSERT INTO `page` (id,parentId) VALUES (2,1);
/* pageInfo */
INSERT INTO `pageInfo` (pageId,languageCode,regionCode) VALUES (1,'de','ZZ');
INSERT INTO `pageInfo` (pageId,languageCode,regionCode) VALUES (1,'en','ZZ');
INSERT INTO `pageInfo` (pageId,languageCode,regionCode) VALUES (1,'nl','ZZ');
INSERT INTO `pageInfo` (pageId,languageCode,regionCode) VALUES (2,'en','ZZ');
INSERT INTO `pageInfo` (pageId,languageCode,regionCode) VALUES (2,'nl','ZZ');
The dilemma:
To retrieve pages with id 2 of all active locales I issue the following SQL statement:
SELECT
p.*, pi.languageCode, pi.regionCode
FROM
page AS p
INNER JOIN pageInfo AS pi
ON pi.pageId = p.id
INNER JOIN locale AS l
ON l.languageCode = pi.languageCode AND l.regionCode = pi.regionCode
WHERE
(p.id = '2')
AND (l.isActive = 'yes')
How would I alter this statement, so that, when id 2 is not available for a particular locale, it automatically falls back on the root page for that locale (that is: where page.parentId IS NULL)? My goal is to have MySQL give me either one, but not both, for the active locales.
I tried:
WHERE
(p.id = '2' OR (p.parentId IS NULL))
But, of course, that gives me two records for locales that actually have id 2 also. I'm pretty sure it's possible (either with UNION, sub selects, or a duplicate join on page) but I'm having a total SQL writers block here. I'd appreciate your help.
How about XOR? "one or the other but not both":
WHERE
(p.id = '5' XOR (p.parentId IS NULL))
^---here
You could order by p.id=5 and use a limit of 1. It's a bit of a hack, but it'll work.
SELECT
p.*, pi.languageCode, pi.regionCode
FROM
page AS p
INNER JOIN pageInfo AS pi
ON pi.pageId = p.id
INNER JOIN locale AS l
ON l.languageCode = pi.languageCode AND l.regionCode = pi.regionCode
WHERE
(p.id = '5' OR (p.parentId IS NULL))
AND (l.isActive = 'yes')
ORDER BY p.id = '5' DESC
LIMIT 1
Use LEFT JOINs and join both tables twice. The second time you join them specifically for the case of p.parentId IS NULL.
In the SELECT list use IFNULLs. First arguments are for the id specified, second ones are the fallbacks, i.e. the values for the root page.
SELECT
p.*,
IFNULL(l.languageCode, lr.LanguageCode) AS languageCode,
IFNULL(l.regionCode, lr.regionCode) AS regionCode
FROM
page AS p
LEFT JOIN pageInfo AS pi
ON pi.pageId = p.id
LEFT JOIN locale AS l
ON l.languageCode = pi.languageCode AND l.regionCode = pi.regionCode
LEFT JOIN pageInfo AS pir
ON pir.pageId = p.id AND p.parentId IS NULL
LEFT JOIN locale AS lr
ON lr.languageCode = pir.languageCode AND lr.regionCode = pir.regionCode
WHERE
(p.id = '5' AND l.isActive = 'yes')
OR (p.parentId IS NULL AND lr.isActive = 'yes')