SQL define table for treelike structure - sql

In previous versions of Visual studio there was a way to build DB using diagrams.
In 2012 they took out that possibility.
I need to create script which creates table for category tree.
CREATE TABLE [dbo].[Categories]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY,
[Name] NVARCHAR(50) NOT NULL,
[ParentId] INT NOT NULL DEFAULT 0,
[FK_Parent] int FOREIGN KEY ([ParentId]) REFERENCES [Categories]([Id]) NOT NULL
)
If I create table like this, I cannot add top level records.

Define top-level records as having a NULL FK_Parent. Just change your definition to allow nulls.
CREATE TABLE [dbo].[Categories]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY,
[Name] NVARCHAR(50) NOT NULL,
[ParentId] INT NOT NULL ,
---llow NULL FK_Parent for top-level
CONSTRAINT [FK_Parent] FOREIGN KEY ([ParentId]) REFERENCES [Categories]([Id])
)

Related

How to use constraints to force two child items be from the same parent?

I have a Jobs table that holds jobs.
I have a Tasks table that holds tasks that belong to a job (1:many).
I have a Task_Relationships table that holds the data about which tasks depend on other tasks within a job.
I have 2 jobs, each job has 3 tasks and within the jobs the tasks are related as in the diagram. The Task_Relationships table is to represent that tasks within a job have dependencies between them.
How to ensure that when I add an entry to the Task_Relationships table say (1,2) representing the fact that task 1 is related to task 2, that tasks 1 and 2 are in the same job? I'm trying to enforce this through keys and not through code.
drop table if exists dbo.test_jobs
create table dbo.test_jobs (
[Id] int identity(1,1) primary key not null,
[Name] varchar(128) not null
)
drop table if exists dbo.test_tasks
create table dbo.test_tasks (
[Id] int identity(1,1) primary key not null,
[Job_Id] int not null,
[Name] varchar(128) not null
constraint fk_jobs foreign key ([Id]) references dbo.test_jobs(Id)
)
drop table if exists dbo.test_task_relationships
create table dbo.test_task_relationships (
[Id] int identity(1,1) not null,
[From_Task] int not null,
[To_Task] int not null
constraint fk_tasks_from foreign key ([From_Task]) references dbo.test_tasks(Id),
constraint fk_tasks_to foreign key ([To_Task]) references dbo.test_tasks(Id)
)
A reliance on identity columns as primary keys is not helping you here. And it is a logic fault to use an identity column in the relationship table IMO. Surely you do not intend to allow multiple rows to exist in that table with the same values for <from_task, to_task>.
Imagine the child table defined as:
create table dbo.test_tasks (
Job_Id int not null,
Task_Id tinyint not null,
Name varchar(128) not null,
constraint pk_tasks primary key clustered (Job_Id, Task_Id),
constraint fk_jobs foreign key ([Job_Id]) references dbo.test_jobs(Id)
);
Now your relationship table can be transformed into:
create table dbo.test_task_relationships (
From_Job int not null,
From_Task tinyint not null,
To_Job int not null,
To_Task tinyint not null
);
I'll leave it to you to complete the DDL but that should make your goal trivial.
You can declare a superkey in the Task table that includes the Job_Id column as well as columns from an existing key.
create table dbo.test_tasks (
[Id] int identity(1,1) primary key not null,
[Job_Id] int not null,
[Name] varchar(128) not null
constraint fk_jobs foreign key ([Id]) references dbo.test_jobs(Id),
constraint UQ_Tasks_WithJob UNIQUE (Id, Job_Id)
)
You can then add the Job_Id column to the relationships table and include it in both foreign key constraints:
create table dbo.test_task_relationships (
[Id] int identity(1,1) not null,
[From_Task] int not null,
Job_Id int not null,
[To_Task] int not null
constraint fk_tasks_from foreign key ([From_Task], Job_Id) references dbo.test_tasks(Id, Job_Id),
constraint fk_tasks_to foreign key ([To_Task], Job_Id) references dbo.test_tasks(Id, Job_Id)
)
There is now no way for the table to contain mismatched tasks. If necessary, wrap this table in a view/trigger if you don't want to expose the presence of the job_id column to applications and to automatically populate it during insert.

Creating SQL database. with multiple primary and foreign keys

I'm currently working through an assignment that is asking me to create a SQL database using SQL Server Express. This is what it's asking for:
CREATE DATABASE USING SQL
And this is the code I have tried running;
CREATE DATABASE db_Library
Go
USE db_Library
CREATE TABLE tbl_library_branch
(
library_branch_branch_id INT PRIMARY KEY NOT NULL IDENTITY (1,1),
library_branch_branch_name VARCHAR(50) NOT NULL,
library_branch_address VARCHAR(50) NOT NULL
);
CREATE TABLE tbl_publisher
(
library_publisher_publisher_name VARCHAR(50) PRIMARY KEY NOT NULL,
library_publisher_address VARCHAR(50) NOT NULL,
library_publisher_phone INT NOT NULL
);
CREATE TABLE tbl_books
(
library_books_book_id INT PRIMARY KEY NOT NULL IDENTITY (1,1),
library_books_title VARCHAR(50) NOT NULL,
library_books_publisher_name VARCHAR(50) NOT NULL CONSTRAINT fk_library_books_publisher_name FOREIGN KEY REFERENCES tbl_publisher(library_publisher_publisher_name) ON UPDATE CASCADE ON DELETE CASCADE
);
CREATE TABLE tbl_book_authors
(
library_book_authors_book_id INT NOT NULL CONSTRAINT fk_library_book_authors_book_id FOREIGN KEY REFERENCES tbl_books(library_books_book_id) ON UPDATE CASCADE ON DELETE CASCADE,
library_book_authors_author_name VARCHAR(50) NOT NULL
);
CREATE TABLE tbl_book_copies
(
library_book_copies_book_id INT NOT NULL CONSTRAINT fk_library_book_copies_book_id FOREIGN KEY REFERENCES tbl_books(library_books_title),
library_book_copies_branch_id INT NOT NULL,
library_book_copies_number_of_copies INT NOT NULL
);
CREATE TABLE tbl_book_loans
(
library_book_loans_book_id INT NOT NULL,
library_book_loans_branch_id INT NOT NULL,
library_book_loans_card_no INT NOT NULL,
library_book_loans_date_out INT NOT NULL,
library_book_loans_date_due INT NOT NULL
);
CREATE TABLE tbl_borrower
(
library_borrower_card_no INT PRIMARY KEY NOT NULL IDENTITY (1,1),
library_borrower_name VARCHAR(50) NOT NULL,
library_borrower_address VARCHAR(50) NOT NULL,
library_borrower_phone VARCHAR(50) NOT NULL
);
Using the library "Books" as an example it looks like I need to have BoodID as a primary key and Title as a primary key, but you can't have more than one primary key per table..
Then I have to take BookID from the Book_Copies table and the Book_Loans table connect to the primary key of Title in Books?
I'm beyond stuck at this point and would appreciate any resources you think could help.
There is no need to be so verbose. I think you want something more like this (for two tables):
CREATE TABLE tbl_publisher (
publisher_id int IDENTITY(1, 1) PRIMARY KEY,
publisher_name VARCHAR(50) NOT NULL UNIQUE,
address VARCHAR(50) NOT NULL,
phone INT NOT NULL
);
CREATE TABLE books (
book_id INT IDENTITY (1,1) PRIMARY KEY,
title VARCHAR(50) NOT NULL UNIQUE,
publisher_id INT NOT NULL CONSTRAINT fk_books_publisher__id FOREIGN KEY REFERENCES tbl_publisher(publisher_id) ON UPDATE CASCADE ON DELETE CASCADE
);
Notes:
Stick with synthetic primary keys for all the tables. That is, identity columns.
Other columns can be declared to be unique. That is fine.
I type quite fast. And yet I would quickly wary of typing library_book_ over and over. Such repetition just makes it harder to write and read queries.

Can't figure out how to make a subquery

CREATE TABLE TBLTeams
(
teamnm varchar(30) NOT NULL,
teamid varchar(10),
rondenm varchar(10)
primary key(teamnm)
)
CREATE TABLE TBLWedstrijd
(
thuisteamnm varchar(30) NOT NULL,
uitteamnm varchar(30) NOT NULL,
wedstrijdid varchar(10)
primary key(wedstrijdid)
)
alter table TBLWedstrijd add foreign key (thuisteamnm) references TBLTeams(teamnm)
alter table TBLWedstrijd add foreign key (uitteamnm) references TBLTeams(teamnm)
CREATE TABLE TBLUitslag
(
thuisteamnm varchar(30) NOT NULL,
uitteamnm varchar(30) NOT NULL,
wedstrijdid varchar(10) NOT NULL,
uitteampunt int,
thuisteampunt int
primary key(thuisteamnm)
)
alter table TBLUitslag add foreign key (wedstrijdid) references TBLWedstrijd(wedstrijdid)
If I update teamnm in TBLTeams how can I update reference in TBLWedstrijd uitteamnm. I know its a subquery but I really dont know how.
You're going about it a bit wrong. If you're going to change the teamname, you shouldn't use it as a key (Since that will break all references).
You'll want to reference their IDs from the TBLWedstrijd instead of using their name.
So your statements will become:
CREATE TABLE TBLWedstrijd
(
wedstrijdid varchar(10),
thuisteamid varchar(10) NOT NULL,
uitteamid varchar(10) NOT NULL,
primary key(wedstrijdid)
)
alter table TBLWedstrijd add foreign key (thuisteamid) references TBLTeams(teamid)
alter table TBLWedstrijd add foreign key (uitteamid) references TBLTeams(teamid)
The same is valid for your table TBLUitslag, you should only reference TBLWedstrijd, since that one already holds the info about which teams are playing. Not to mention, the score is pretty much part of a game anyway so it doesn't make a lot of sense to seperate those into 2 tables. So that becomes:
CREATE TABLE TBLWedstrijd
(
wedstrijdid varchar(10),
thuisteamid varchar(10) NOT NULL,
uitteamid varchar(10) NOT NULL,
uitteampunt int,
thuisteampunt int
primary key(wedstrijdid)
)
This is called "table normalisation" if you wanted to google some stuff for more info about it.

SQL Server : create error how to write database name with the table name

CREATE DATABASE agom COLLATE Arabic_CI_AS
CREATE TABLE Branches
(
ID INT PRIMARY KEY NOT NULL IDENTITY,
NAME VARCHAR(255) NOT NULL
)
CREATE TABLE agom.Brands
(
ID INT PRIMARY KEY NOT NULL IDENTITY,
NAME VARCHAR(255) NOT NULL
)
CREATE TABLE agom.Work_Order
(
NUMBER INT NOT NULL,
BRANCHID INT NOT NULL,
BRANDID INT NOT NULL,
WDATE DATE NOT NULL,
REPAIRSTATUS VARCHAR(255),
REPAIRCOST VARCHAR(255),
REMARK VARCHAR(500),
PRIMARY KEY (NUMBER,BRANCHID,BRANDID)
)
CREATE TABLE agom.Profiles
(
ID INT PRIMARY KEY NOT NULL IDENTITY,
USERNAME VARCHAR(25) NOT NULL,
PASS VARCHAR(25) NOT NULL
)
ALTER TABLE agom.Work_Order
ADD CONSTRAINT branchfk
FOREIGN KEY (BRANCHID) REFERENCES Branches(ID)
ALTER TABLE agom.Work_Order
ADD CONSTRAINT brandfk
FOREIGN KEY (BRANDID) REFERENCES Brands(ID)
I get an error that cannot create table
I try to write database name with the table name db.tablename but it's not working
I need to create the database then create the tables and its constraints but I don't know where is the error.I am a sql noob
It's never Database.Table.
It's either Table, or Schema.Table, or Database.Schema.Table, or Server.Database.Schema.Table.
You probably just want to insert USE agom right after create database, and then only refer to tables by name.
Alternatively, you can refer to your tables as agom.dbo.Work_Order, dbo being the default database schema.
See Using Identifiers As Object Names for general reference.

SQL SMS - Error - There is already an object named "genre" in the database

I'm trying to create a hypothetical videostore database and this error message comes up everytime I execute this query:
DROP DATABASE videostore
CREATE DATABASE videostore
CREATE TABLE genre
(
genre_id INT NOT NULL PRIMARY KEY IDENTITY,
genre_name VARCHAR(15) NOT NULL
);
CREATE TABLE classification
(
rating VARCHAR(2) NOT NULL CONSTRAINT classification_pk PRIMARY KEY,
description VARCHAR(100) NOT NULL,
minimum_age INT NULL,
);
CREATE TABLE format
(
format_id INT NOT NULL CONSTRAINT format_pk PRIMARY KEY IDENTITY,
format_name VARCHAR(8) NOT NULL,
purchase_cost FLOAT NOT NULL
);
CREATE TABLE rental_cost
(
rental_cost_id INT NOT NULL CONSTRAINT rental_cost_pk PRIMARY KEY IDENTITY,
rental_name VARCHAR(15) NOT NULL,
rental_cost FLOAT NOT NULL,
rental_days TINYINT NOT NULL
);
CREATE TABLE customer
(
customer_id INT NOT NULL CONSTRAINT customer_pk PRIMARY KEY IDENTITY,
first_name VARCHAR(20) NOT NULL,
surname VARCHAR(20) NOT NULL,
dob DATETIME NOT NULL,
home_address VARCHAR(50) NOT NULL,
contact_number VARCHAR(10) NOT NULL,
referrer_id INT NULL FOREIGN KEY REFERENCES customer(customer_id),
);
CREATE TABLE movie
(
movie_id INT NOT NULL CONSTRAINT movie_pk PRIMARY KEY IDENTITY,
movie_name VARCHAR(40) NOT NULL,
year SMALLINT NOT NULL,
duration SMALLINT NULL,
descrip VARCHAR(120) NULL,
classification VARCHAR(2) NOT NULL FOREIGN KEY REFERENCES classification(rating),
rental_cost_id INT NOT NULL FOREIGN KEY REFERENCES rental_cost(rental_cost_id),
);
CREATE TABLE copy
(
copy_id INT NOT NULL CONSTRAINT copy_pk PRIMARY KEY IDENTITY,
movie_id INT NOT NULL FOREIGN KEY REFERENCES movie(movie_id),
format_id INT NOT NULL FOREIGN KEY REFERENCES format(format_id),
);
CREATE TABLE rental
(
rental_id INT NOT NULL CONSTRAINT rental_pk PRIMARY KEY IDENTITY,
copy_id INT NOT NULL FOREIGN KEY REFERENCES copy(copy_id),
customer_id INT NOT NULL FOREIGN KEY REFERENCES customer(customer_id),
rental_date DATETIME NOT NULL,
return_date DATETIME NULL
);
CREATE TABLE genre_movie
(
genre_id INT NOT NULL FOREIGN KEY REFERENCES genre(genre_id),
movie_id INT NOT NULL FOREIGN KEY REFERENCES movie(movie_id),
CONSTRAINT genre_movie_pk PRIMARY KEY (genre_id, movie_id)
);
(Sorry it's not in the correct format for reading a script with ease, I just really couldn't work out how to do that.)
Basically when I execute the SQL script it tells me that the object 'genre' already exists, but I can't see it anywhere else in my code.
And the table shouldn't already exist because I drop the database each time the script is executed right?
Sidenote - if there's a better way to make it so the database is dropped only if it exists please help me with that also.
Appreciate it.
I think you need to add USE videostore after the CREATE DATABASE videostore. Otherwise you are creating tables in whatever database you are currently in.
I think you are executing this in the context of the master database. If you check it you will probably see all your tables are actually in master.
Change the first part to this:
DROP DATABASE videostore
CREATE DATABASE videostore
USE videostore
CREATE TABLE genre
It's generally best to execute sql statements when required - try:
DROP DATABASE videostore
GO
CREATE DATABASE videostore
GO
USE videostore
CREATE TABLE genre
(
genre_id INT NOT NULL PRIMARY KEY IDENTITY,
genre_name VARCHAR(15) NOT NULL
);
GO
etc.