T-SQL constraint to check if value is either 0 OR unique - sql

I'm designing a DB where employees need to be activated by an Admin. When a new employee registers, their workstation (int) gets set to 0 by default. However, I also can't allow to have more than 1 employee per workstation. So I was thinking if there's a way to allow for duplicates of the value 0, but enforce that any other number be unique.

You can use a partial unique index. For example:
create unique index ix1 on employees (workstation) where workstation <> 0;
As in:
create table employees (
id int,
name varchar(10),
workstation int not null
);
create unique index ix1 on employees (workstation) where workstation <> 0;
insert into employees (id, name, workstation) values (1, 'Anne', 100);
insert into employees (id, name, workstation) values (2, 'Peter', 101);
insert into employees (id, name, workstation) values (3, 'Joel', 100); -- fails
insert into employees (id, name, workstation) values (4, 'Niko', 0);
insert into employees (id, name, workstation) values (5, 'Akina', 0); -- succeeds
This is one of the constraints that you cannot enforce using traditional constraints.
See running example at db<>fiddle. As you see only Joel, 100 is rejected. The other two cases with workstation = 0 are inserted.

Related

How to add a BIT column in SQL

I want to add a BIT column to a table. I have provided the statement to do so, but an error declares the BIT in my statement as a invalid datatype. What would be the correct way to add a bit column?
ALTER TABLE Persons
ADD is_person BIT NULL
[You should specify database you use; this is Oracle example, see if it helps].
There's no such a datatype in Oracle, so you'd use NUMBER and constrain it:
SQL> create table persons
2 (id number,
3 bit number(1,0) check (bit in (0, 1)) --> this
4 );
Table created.
A few examples:
SQL> insert into persons (id, bit) values (1, 2);
insert into persons (id, bit) values (1, 2)
*
ERROR at line 1:
ORA-02290: check constraint (SCOTT.SYS_C008434) violated
SQL> insert into persons (id, bit) values (1, 1);
1 row created.
SQL> insert into persons (id, bit) values (1, 0);
1 row created.
SQL> insert into persons (id, bit) values (1, 10);
insert into persons (id, bit) values (1, 10)
*
ERROR at line 1:
ORA-01438: value larger than specified precision allowed for this column
SQL>
Or, if you'd want to add it (as table already exists), then
alter table persons add bit number(1, 0) check (bit in (0, 1));

Can anyone help me with this SQL code error?

Can anyone help me with this error?
Database info:
CREATE DATABASE School;
Use School to create first table:
CREATE TABLE Classes
(
class_id INT,
name Varchar(45),
dept Char(4),
number CHAR(4),
section Char(2),
location Varchar(45),
meeting_time varchar(45),
PRIMARY KEY(class_id)
);
INSERT INTO Classes
VALUES (000001, 'Intro. to databases', 'info', '1620', '1a', 'sarpy214', 'm/w 1-2:45 pm');
INSERT INTO Classes (class_id, name, dept, number, section, location)
VALUES (000002, 'intro. to sql', 'info', '2630', 'ww', 'online');
INSERT INTO Classes
VALUES (000003, 'Software Engineering I', 'info', '1325', '4c', 'socmahoney205', 't/h 10-11:45 pm');
INSERT INTO Classes (class_id, name, dept, number, section, location)
VALUES (000004, 'Software Engineering II', 'info', '1335', 'ww', 'online');
INSERT INTO Classes
VALUES (000005, 'How to leave the shire & live forever', 'ring', '1001', '1r', 'socmahoney214', 'f 10-11:45 am');
INSERT INTO Classes (class_id, name, dept, number, section, location)
VALUES (000006, 'Living with the demon inside', 'psyc', '1668', 'ww', 'online');
INSERT INTO Classes
VALUES (000007, 'Internet Scripting jedi mastery', 'info', '2430', '2b', 'socmahoney205', 'm/w 10-11:45 am');
UPDATE Classes
SET meeting_time = 't/h 10-11:45 am'
WHERE class_id = 000003;
SELECT * FROM Classes;
Now create 2nd table:
CREATE TABLE Enrol
(
stu_id int,
class_id int,
grade char(1),
PRIMARY KEY (stu_id),
FOREIGN KEY (stu_id) REFERENCES Students(Stu_id),
FOREIGN KEY (class_id) REFERENCES Classes(class_id)
);
INSERT INTO Enrol VALUES (0000001, 000002, 'A');
INSERT INTO Enrol (stu_id, class_id) VALUES (0000002, 000002);
INSERT INTO Enrol VALUES (0000005, 000001, 'D');
INSERT INTO Enrol (stu_id, class_id) VALUES (0000006, 000005);
INSERT INTO Enrol VALUES (0000003, 000006, 'C');
SELECT * FROM Enrol;
Create 3rd table:
CREATE TABLE Students
(
Stu_id INT PRIMARY KEY,
fname VARCHAR(45),
lname VARCHAR(45),
area_code CHAR(3),
phone VARCHAR(8)
);
INSERT INTO Students
VALUES (000001, 'patty', 'melt', '402', '234-9876');
INSERT INTO Students
VALUES (000002, 'bill', 'fold', '402', '531-6222');
INSERT INTO Students
VALUES (000003, 'sam', 'winchester', '402', '234-2346');
INSERT INTO Students
VALUES (000004, 'luke', 'skywalker', '402', '543-1234');
INSERT INTO Students
VALUES (000005, 'charlie', 'kelly', '402', '234-6859');
INSERT INTO Students
VALUES (000006, 'bilbo', 'baggins', '531', '646-3828');
SELECT * FROM Students
enter image description here
the issue that you used aggregated function and in the group by you need to put all non aggregated function
so add in the group by
GROUP BY S.STU_ID, S.FNAME, S.LNAME;
The "error" is a minor one and several RDBMS will even ignore it.
You see, if you have a tuple such as (ID, FNAME), it is obvious that every ID maps to its own FNAME. It can't be otherwise. So, GROUPing by ID, or grouping by ID and FNAME, is exactly the same thing.
While, on the other hand, in a complex JOIN, you might have different values of a third column from a different table for the same ID value; in that case, you cannot SELECT both ID and this third column when grouping by ID, because the system wouldn't have enough information to decide which, among the possible different values of the third column, should go with each ID. In this case, to solve the quandary you need to add this third column to the GROUP BY, thereby increasing the cardinality of ID in the response: you might now have 1, JOHN SMITH, YELLOW and 1, JOHN SMITH, RED.
Here, your SELECT is of the first kind, but the database engine does not realize or care for this, and insists that you specify a full GROUP with all the fields in the select, even if one is a primary key and the others are in the same table.
So,
GROUP BY S.STU_ID, S.FNAME, S.LNAME

POSTGRES - handle several unique indexes differently in ON CONFLICT clause

I have a table with several unique indexes. Is it possible to ON CONFLICT UPDATE only on one of them and DO NOTHING on all others, handling with DO NOTHING future unique indexes without going back and modifying code or at least existing ones. Ex:
ON CONFLICT (name, age)
DO UPDATE SET
occupation = 'teacher'
ELSE ON CONFLICT(all others) DO NOTHING;
Right now, of course, it throws an error for all other indexes besides 1st one. Or alternatively what is the best way to handle it so no errors are thrown. Thank you.
CREATE UNIQUE INDEX index1 ON contact USING btree (name, age);
CREATE UNIQUE INDEX index2 ON contact USING btree (name, address) WHERE (address IS NOT NULL);
CREATE UNIQUE INDEX index3 ...
CREATE UNIQUE INDEX index4 ...
INSERT INTO contact
(name,
age,
address,
occupation)
VALUES
('John',
25,
'1 main st',
'doctor')
ON CONFLICT (name, age)
DO UPDATE SET
occupation = 'teacher';
How about just avoiding the insert? It's a bit verbose and will need to be kept up to date with your unique constraints, but at least it shouldn't error.
INSERT INTO contact
(name,
age,
address,
occupation)
SELECT
'John',
25,
'1 main st',
'doctor'
WHERE NOT EXISTS (
SELECT 1
FROM contact WHERE
(name, address) = ('John', '1 main st')
OR (... next unique constraint...)
)
ON CONFLICT (name, age)
DO UPDATE SET
occupation = 'teacher';

Creating a Random Number in a Local Temporary Table

today I have a bit of a dilemma. I was tasked with creating a local temporary table that would contain faculty members first name, last name, campus, and new id number. The ID number would be a randomly generated 5 digit number. (I am using Microsoft SQL Server Management Studio)
My problem is I am new to random number generation and local temp tables. I believe most of my code is correct expect for the "random id number" I need to make. I have googled my problem only thing is there seem to be many ways to create "random" numbers and I don't understand the method behind it.
I've included my code and the database below.
My Code:
SELECT FirstName, LastName, Campus, LEFT(CAST(CAST(CEILING(RAND() *100000000) AS bigint) AS varchar), 5) AS IDnumber
INTO #LocalTemp1
FROM Faculty;
SELECT * FROM #LocalTemp1
Database:
CREATE TABLE Faculty
(Faculty_ID INT PRIMARY KEY IDENTITY,
LastName VARCHAR (20) NOT NULL,
FirstName VARCHAR (20) NOT NULL,
Department VARCHAR (10) SPARSE NULL,
Campus VARCHAR (10) SPARSE NULL);
INSERT INTO Faculty VALUES ('Brown', 'Joe', 'Business', 'Kent');
INSERT INTO Faculty VALUES ('Smith', 'John', 'Economics', 'Kent');
INSERT INTO Faculty VALUES ('Jones', 'Sally', 'English', 'South');
INSERT INTO Faculty VALUES ('Black', 'Bill', 'Economics', 'Kent');
INSERT INTO Faculty VALUES ('Green', 'Gene', 'Business', 'South');
CREATE TABLE Course
(Course_ID INT PRIMARY KEY IDENTITY,
Ref_Number CHAR (5) CHECK (Ref_Number LIKE '[0-9][0-9][0-9][0-9][0-9]'),
Faculty_ID INT NOT NULL REFERENCES Faculty (Faculty_ID),
Term CHAR (1) CHECK (Term LIKE '[A-C]'),
Enrollment INT NULL DEFAULT 0 CHECK (Enrollment < 40))
INSERT INTO Course VALUES ('12345', 3, 'A', 24);
INSERT INTO Course VALUES ('54321', 3, 'B', 18);
INSERT INTO Course VALUES ('13524', 1, 'B', 7);
INSERT INTO Course VALUES ('24653', 1, 'C', 29);
INSERT INTO Course VALUES ('98765', 5, 'A', 35);
INSERT INTO Course VALUES ('14862', 2, 'B', 14);
INSERT INTO Course VALUES ('96032', 1, 'C', 8);
INSERT INTO Course VALUES ('81256', 5, 'A', 5);
INSERT INTO Course VALUES ('64321', 2, 'C', 23);
INSERT INTO Course VALUES ('90908', 3, 'A', 38);
A source i was looking at, still need a better understanding: Generating a random & unique 8 character string using MySQL
EDIT: Running the query actually doesn't display any information, just the column names.
EDIT: Still would need help, I don't know if editing this post will bump it
EDIT: So I decided to try and just use "RAND()" on its own. I can now see the results being displayed, however, the number sets are not all random.
EDIT: Updated the formula for the RANDOM ID, it works in a way, just not making every row a unique random number.

SQL set UNIQUE only for two columns

I would like for example that user can add name JHONE and age 25, so next time he can add JHONE, 26 or ALEX 25, BUT not JHONE, 25 again.
So I'm looking for two column unique NOT separately.
P.S. I'm sorry if same question was mentioned before.
EDIT:
This is my example:
Would like to make userIdG and doWithCar will be like this
102163096246025413003 View
102163096246025413003 Buy
102163096246025413003 Let
102163096246025413003 Sell
And for Id = 102163096246025413003 you can't add any more values, BECAUSE column doWithCar will have only 4 possible choice view, buy, rent and sell
You could specify more than one column in UNIQUE:
CREATE TABLE tab(ID INT IDENTITY(1,1) PRIMARY KEY, name VARCHAR(100), age INT
,UNIQUE(name, age));
INSERT INTO tab(name, age) VALUES ('John', 25);
INSERT INTO tab(name, age) VALUES ('John', 26);
-- INSERT INTO tab(name,age) VALUES ('John', 25);
-- Violation of UNIQUE KEY constraint 'UQ__tab__CF0426FD76D3370A'.
-- Cannot insert duplicate key in object 'dbo.tab'.
-- The duplicate key value is (John, 25).
-- The statement has been terminated.
SELECT * FROM tab;
LiveDemo
Note:
You should store date of birth and not age itself (or make age calculated column and set UNIQUE(name, dob)).
this is what I do not understand) how database will know that it should be two columns as unique and not each column is unique
These are different concepts. DB "knows" it from UNIQUE constraint definition:
UNIQUE(userIdG,doWithCar) -- pair of column is unique
!=
UNIQUE(userIdG),UNIQUE(doWithCar) -- each column is unique