Setting a column based on conditions when INSERTING data in ORACLE - sql

Currently working on a basketball performance database. The issue I'm having is storing the winner of a match.
Match table is currently like so:
CREATE TABLE Matches(
M_ID int CONSTRAINT pk_Match PRIMARY KEY,
M_Date Date NOT NULL,
M_Location varchar(20),
M_HomeTeam int NOT NULL,
M_AwayTeam int NOT NULL,
M_HomeScore int NOT NULL,
M_AwayScore int NOT NULL,
M_Winner int,
CONSTRAINT fk_TeamHome foreign key (M_HomeTeam) REFERENCES Team(T_ID),
CONSTRAINT fk_TeamAway foreign key (M_AwayTeam) REFERENCES Team(T_ID)
)
What I want is the value of M_Winner to be set to M_HomeTeam & M_AwayTeam foreign keys based on their scores.
I've been able to do this with this update statement
UPDATE Matches
SET M_Winner = CASE
WHEN M_HomeScore > M_AwayScore
THEN M_HomeTeam
WHEN M_AwayScore > M_HomeScore
THEN M_AwayTeam
END;
However I need it to work when the data is inserted.
Any ideas?

In Oracle 11g+, you can use a virtual computed column:
ALTER TABLE matches
ADD m_winner as (CASE WHEN M_HomeScore > M_AwayScore
THEN M_HomeTeam
WHEN M_AwayScore > M_HomeScore
THEN M_AwayTeam
END)

You can define a trigger for that:
CREATE OR REPLACE TRIGGER trg_ins_match
BEFORE INSERT ON Matches
FOR EACH ROW
BEGIN
IF :new.M_HomeScore > :new.M_AwayScore THEN
:new.M_Winner = :new.M_HomeTeam
ELSE
:new.M_Winner = :new.M_AwayTeam
END IF;
END;
Read about triggers in the Oracle Developer's Guide

Related

Use a condition while creating a table in SQL

I'd like to create a table with a condition
create table TOTO
(
Id int not null,
zip as (if(zip > '00999' and zip < '96000') then zip) ,
PRIMARY KEY (Id)
);
All I get is an error message.
Do you know how to do that with the "zip" in type char ?
Thank you for your help !
You may want to use CHECK constraint instead
CREATE TABLE TOTO
(
Id int NOT NULL,
zip char,
PRIMARY KEY (Id),
CHECK (zip > '00999' AND zip < '96000')
);
You can get this done either using a CHECK CONSTRAINT or using a BEFORE INSERT or INSTEAD OF trigger
An example:
CREATE TRIGGER ChkZip
ON TOTO
INSTEAD OF INSERT
AS
BEGIN
IF (inserted.zip > '00999' and inserted.zip < '96000')
BEGIN
INSERT INTO TOTO (id,zip) VALUES (insered.id, inserted.zip)
END
ELSE
BEGIN
RAISERROR ('The entered zip code doesn't match criteria.' ,10,1)
ROLLBACK TRANSACTION
END
END
CREATE TABLE TOTO
(
Id INT NOT NULL,
zip VARCHAR2(10),
PRIMARY KEY (Id),
CONSTRAINT CHK_zip CHECK (zip > to_number('00999') AND zip < to_number('96000'))
);
You could use check constraint - the above script is based on Oracle Sql function
You need to create a new CHECK constraint so that your field is guaranteed to comply with this constraint each time it is set or modified (insert or update).
Here is an example adapted to SQL server (as you seem to be using that dbms) where the constraint is named so you can identify it more easily (better for maintainability)
create table TOTO
(
Id int not null,
zip char ,
PRIMARY KEY (Id),
CONSTRAINT CHK_zip CHECK(zip > '00999' and zip < '96000')
);
Note that you could formulate it using patterns as in the link I provided.

Using sql function on CHECK constraint for newly inserted row

First of all i need help with this for my bachelor thesis. I'm doing the whole database on sql server 2008 Release 2.
The problem is with check constraint that is using a function that is working on her own but not with the use in the constraint. The result of the constraint should be something like this: An employee could go only on one bussines trip per day.
Table Bussines trips:
CREATE TABLE SluzebniCesta(
idSluzCesty int PRIMARY KEY NOT NULL,
DatumCesty DATE NOT NULL,
CasOdjezdu TIME(0) NOT NULL,
CasPrijezdu TIME(0),
CONSTRAINT Odjezd_prijezd CHECK(CasPrijezdu > DATEADD(hour,2,CasOdjezdu))
);
Table that contains the employs that goes on bussines trip:
CREATE TABLE ZamNaCeste(
idZamNaCeste int PRIMARY KEY NOT NULL,
SluzebCestaID int NOT NULL,
ZamestnanecID int NOT NULL,
FOREIGN KEY (ZamestnanecID) REFERENCES Zamestnanec(idZamestnance),
FOREIGN KEY (SluzebCestaID) REFERENCES SluzebniCesta(idSluzCesty)
);
Foreign key ZamestnanecID is an employee's id and SluzebCestaID is the bussines trip id.
Now the function :
CREATE FUNCTION myCheckZamNaCeste(#SluzebCestaID int, #ZamestnanecID int)
RETURNS int
AS
BEGIN
DECLARE #retVal int;
DECLARE #Zamestnanec int;
DECLARE #SluzebniCesta int;
SET #Zamestnanec = (SELECT idZamestnance FROM Zamestnanec WHERE idZamestnance=#ZamestnanecID);
SET #SluzebniCesta = (SELECT idSluzCesty FROM SluzebniCesta WHERE idSluzCesty=#SluzebCestaID);
IF EXISTS ( SELECT DatumCesty FROM SluzebniCesta
WHERE idSluzCesty = #SluzebniCesta
AND DatumCesty IN (SELECT DatumCesty FROM ZamNaCeste
LEFT JOIN SluzebniCesta
ON ZamNaCeste.SluzebCestaID = SluzebniCesta.idSluzCesty
WHERE ZamestnanecID=#Zamestnanec))
BEGIN
SET #retVal=0;
END
ELSE
BEGIN
SET #retVal=1;
END
return #retVal
END
GO
And the alter table for the table that contains evidence of employee and their bussines trips:
ALTER TABLE ZamNaCeste
ADD CONSTRAINT check_cesty_zamestnance CHECK(dbo.myCheckZamNaCeste(SluzebCestaID,ZamestnanecID)=1);
And when I try to enter any new row the constraint is broken even if the function gives the right data. return 1 is the good result ....
In the first place, I'm not sure but it looks like the two set statements in the function are going out to retrieve from tables exactly the same values they already have from being passed in as parameters.
In the second place, I don't see anything limiting trips in the same day. Anywhere.
If you wanted to limit a trip by an employee to one per day, that is easy.
CREATE TABLE ZamNaCeste(
idZamNaCeste int PRIMARY KEY NOT NULL,
SluzebCestaID int NOT NULL,
ZamestnanecID int NOT NULL,
TripDate date not null,
FOREIGN KEY (ZamestnanecID) REFERENCES Zamestnanec(idZamestnance),
FOREIGN KEY (SluzebCestaID) REFERENCES SluzebniCesta(idSluzCesty),
constraint UQ_OneTripPerDay unique( ZamestnanecID, TripDate )
);
The unique constraint ensures the same employee cannot log more than one trip on the same day.
Well in the end i solved with a more sophisticated and better looking solution. The employ is limited with the times of arrival and departure. And i solved it with a function that returns number of incorrect occurences, if its zero than its all right and it works:
SELECT COUNT(*) FROM(SELECT * FROM SluzebniCesta JOIN ZamNaCeste
ON SluzebniCesta.idSluzCesty = ZamNaCeste.SluzebCestaID) AS a
JOIN (SELECT * FROM SluzebniCesta2 JOIN ZamNaCeste
ON SluzebniCesta.idSluzCesty = ZamNaCeste.SluzebCestaID)AS b
ON a.SluzebCestaID b.SluzebCestaID
AND a.CasOdjezdu b.CasOdjezdu
AND a.ZamestnanecID = b.ZamestnanecID
AND (SELECT SluzebniCesta.DatumCesty FROM SluzebniCesta
WHERE SluzebniCesta.idSluzCesty = a.SluzebCestaID) = (SELECT SluzebniCesta.DatumCesty
FROM SluzebniCesta WHERE SluzebniCesta.idSluzCesty = b.SluzebCestaID)

How do you enforce unique across 2 tables in SQL Server

Requirements:
Every employee has a unique ID. (EPID)
A employee can only be either one of below,
FT - Full Time
PT - Part Time
Any employee can never be both FT and PT.
FT & PT have lots of different fields to capture.
Implementation:
Create Table EmpFT( EPID int primary key, F1, F2, etc)
Create Table EmpPT( EPID int primary key, P1, P2, etc)
--This does not prevent same EPID on both EmpFT and EmpPT.
How do you implement No. 3 in database?
I am using SQL Server 2012 standard edition.
Try this method:
CREATE TABLE Emp(EPID INT PRIMARY KEY,
t CHAR(2) NOT NULL, UNIQUE (EPID,t));
CREATE TABLE EmpFT(EPID INT PRIMARY KEY, ... other columns
t CHAR(2) NOT NULL CHECK (t = 'FT'),
FOREIGN KEY (EPID,t) REFERENCES Emp (EPID,t));
CREATE TABLE EmpPT(EPID INT PRIMARY KEY, ... other columns
t CHAR(2) NOT NULL CHECK (t = 'PT'),
FOREIGN KEY (EPID,t) REFERENCES Emp (EPID,t));
You can add check constraints. Something like this for both tables
ALTER TABLE EmpFT
ADD CONSTRAINT chk_EmpFT_EPID CHECK (dbo.CHECK_EmpPT(EPID)= 0)
ALTER TABLE EmpPT
ADD CONSTRAINT chk_EmpPT_EPID CHECK (dbo.CHECK_EmpFT(EPID)= 0)
And the functions like so:
CREATE FUNCTION CHECK_EmpFT(#EPID int)
RETURNS int
AS
BEGIN
DECLARE #ret int;
SELECT #ret = count(*) FROM EmpFT WHERE #EPID = EmpFT.EPID
RETURN #ret;
END
GO
CREATE FUNCTION CHECK_EmpPT(#EPID int)
RETURNS int
AS
BEGIN
DECLARE #ret int;
SELECT #ret = count(*) FROM EmpPT WHERE #EPID = EmpPT.EPID
RETURN #ret;
END
GO
Further reading here:
http://www.w3schools.com/sql/sql_check.asp
http://technet.microsoft.com/en-us/library/ms188258%28v=sql.105%29.aspx
You could create a combined table for all employees. The FT and PT tables could use foreign keys to the employee table.
You cannot have primary keys span tables. So, one method is to create a table employee with the appropriate constraints. This might look like this:
create table employee (
EPID int not null identity(1, 1) primary key,
FTID int references empft(empftid),
PTID int references emppt(empptid),
CHECK (FTID is not null and PTID is null or FTID is null and PTID is not null),
UNIQUE (FTID),
UNIQUE (PTID)
. . .
);
create table empft (
EmpFTId int not null identity(1, 1) primary key,
. . .
);
create table emppt (
EmpPTId int not null identity(1, 1) primary key,
. . .
);
Of course, you could also use triggers if you wanted to.

SQL Server Create Table With Column Unique Not Null and Not Empty(Check)

How to create a table with a column which is unique, not null and not empty(Check)?
I tried below Query
CREATE TABLE Persons
(
P_Id int NOT NULL UNIQUE,
LastName nvarchar(255) NOT NULL,
FirstName nvarchar(255),
Address nvarchar(255),
City nvarchar(255),
CHECK (P_Id>0)
)
When i try to create a table with both UNIQUE and CHECK constraint its throwing following error. Is it possible to use two constraint in a single query?
Major Error 0x80040E14, Minor Error 25501
> CREATE TABLE Persons
(
P_Id int NOT NULL UNIQUE,
LastName nvarchar(255) NOT NULL,
FirstName nvarchar(255),
Address nvarchar(255),
City nvarchar(255),
CHECK (P_Id>0)
)
There was an error parsing the query. [ Token line number = 8,Token line offset = 1,Token in error = CHECK ]. I am using SQL Server 2008.
CREATE TABLE tab
(
id INT,
notnullandnotemptystr VARCHAR(10) NOT NULL UNIQUE CHECK (DATALENGTH(notnullandnotemptystr) > 0)
)
It should be some thing like this.
CREATE TABLE [dbo].[TABLE1](
[COL1] [nvarchar](50) NOT NULL UNIQUE
)
ALTER TABLE [dbo].[TABLE1] WITH CHECK
ADD CONSTRAINT [CK_TABLE1] CHECK (([COL1]<>N''))
for this problem you can use Constraint in sql server
ALTER TABLE TBL WITH CHECK ADD CONSTRAINT [CK_TBL] CHECK
(([dbo].[TBLCheckCustomeUnique](ID)=(1)))
TBLCheckCustomeUnique is a user define function that check this conditions
You can controll the uniqueness of a column or column set by the UNIQUE constraint.
The data stored in the column or column set could be checked/controlled (and forced with various rules) by the CHECK constraint.
The CHECK constraint to achieve your goal is the following:
ALTER TABLE [YourTable]
ADD CONSTRAINT CK_CheckConstraintName
CHECK (LEN([YourColumn]) >= {MinimumColumnWidth})
You can add the constraints in the CREATE TABLE statement or if the table already exists you can add it with the ALTER TABLE .. ADD CONSTRAINT statement.

CHECK CONSTRAINT on multiple columns

I use SQL Server 2008
I use a CHECK CONSTRAINT on multiple columns in the same table to try to validate data input.
I receive an error:
Column CHECK constraint for column
'AAAA' references another column,
table 'XXXX'.
CHECK CONSTRAINT does not work in this way.
Any other way to implement this on a single table without using FK?
Thanks
Here an example of my code
CREATE TABLE dbo.Test
(
EffectiveStartDate dateTime2(2) NOT NULL,
EffectiveEndDate dateTime2(2) NOT NULL
CONSTRAINT CK_CmsSponsoredContents_EffectiveEndDate CHECK (EffectiveEndDate > EffectiveStartDate),
);
Yes, define the CHECK CONSTRAINT at the table level
CREATE TABLE foo (
bar int NOT NULL,
fred varchar(50) NOT NULL,
CONSTRAINT CK_foo_stuff CHECK (bar = 1 AND fred ='fish')
)
You are declaring it inline as a column constraint
...
fred varchar(50) NOT NULL CONSTRAINT CK_foo_fred CHECK (...)
...
Edit, easier to post than describe. Fixed your commas.
CREATE TABLE dbo.Test
(
EffectiveStartDate dateTime2(2) NOT NULL,
EffectiveEndDate dateTime2(2) NOT NULL, --need comma
CONSTRAINT CK_CmsSponsoredContents_EffectiveEndDate CHECK (EffectiveEndDate > EffectiveStartDate) --no comma
);
Of course, the question remains are you using a CHECK constraint where it should be an FK constraint...?
Check constraints can refer to a single column or to the whole record.
Use this syntax for record-level constraints:
ALTER TABLE MyTable
ADD CONSTRAINT MyCheck
CHECK (...your check expression...)
You can simply apply your validation in a trigger on the table especially that either way the operation will be rolled back if the check failed.
I found it more useful for CONSTRAINT using case statements.
ALTER TABLE dbo.ProductStock
ADD
CONSTRAINT CHK_Cost_Sales
CHECK ( CASE WHEN (IS_NOT_FOR_SALE=0 and SAL_CPU <= SAL_PRICE) THEN 1
WHEN (IS_NOT_FOR_SALE=1 ) THEN 1 ELSE 0 END =1 )