So I have a problem, I was wondering is there a way of inserting the (ID VALUES) to each column since I forgot. I have a really long code. Is there a way for me to select a piece of code to paste the number ID values or a Method of some sort? Or is my only option to do it manually?
CREATE TABLE tASTON
(AsM_ID int Primary Key Not Null IDENTITY(1,1),Make Nvarchar(50), Model nvarchar (50))
Insert into tASTON(AsM_ID,Make,Model) Values ('Aston Martin','DB4')
Insert into tASTON (AsM_ID,Make,Model) Values ('Aston Martin','DB5')
Insert into tASTON (AsM_ID,Make,Model) Values ('Aston Martin','DB6')
Insert into tASTON (AsM_ID,Make,Model) Values ('Aston Martin','DB7')
Insert into tASTON (AsM_ID,Make,Model) Values ('Aston Martin','Vanquish') etc...
Seeing it's an IDENTITY column, there's no need to manually INSERT values. This ought to work:
Insert into tASTON(Make,Model) Values ('Aston Martin','DB4')
Update: Removed brand, as it was confusing and a mistake on my part. Replaced Brand with Make, instead.*
Unrelated, but judging by the name of the table, are you really creating one table per brand of car? If so, I'd suggest creating a make and a car table, where you then implement a key relationship between tCar and tMake:
CREATE TABLE tCAR
(
CAR_ID int Primary Key Not Null IDENTITY(1,1)
, MAKE_ID int FOREIGN KEY REFERENCES tMake(MAKE_ID)
, Model nvarchar (50)
)
Related
English is not my native language, so I might have misused words Enumerator and Enumerable in this context. Please get a feel for what I'm trying to say and correct me if I'm wrong.
I'm looking into not having tables for each enumerator I need in my database.
I "don't want" to add tables for (examples:) service duration type, user type, currency type, etc. and add relations for each of them.
Instead of a table for each of them which values will probably not change a lot, and for which I'd have to create relationships with other tables, I'm looking into having just 2 tables called Enumerator (eg: user type, currency...) and Enumerable (eg: for user type -> manager, ceo, delivery guy... and for currency -> euro, dollar, pound...).
Though here's the kicker. If I implement it like that, I'm loosing the rigidity of the foreign key relationships -> I can't accidentally insert a row in users table that will have a user type of some currency or service duration type, or something else.
Is there another way to resolve the issue of having so many enumerators and enumerables with the benefit of having that rigidity of the foreign key and with the benefit of having all of them in just those 2 tables?
Best I can think of is to create a trigger for BEFORE UPDATE and BEFORE INSERT to check if (for example) the column type of user table is using the id of the enumerable table that belongs to the correct enumerator.
This is a short example in SQL
CREATE TABLE [dbo].[Enumerator]
(
[Id] INT NOT NULL PRIMARY KEY,
[Name] VARCHAR(50)
)
CREATE TABLE [dbo].[Enumerable]
(
[Id] INT NOT NULL PRIMARY KEY,
[EnumeratorId] INT NOT NULL FOREIGN KEY REFERENCES Enumerator(Id),
[Name] VARCHAR(50)
)
INSERT INTO Enumerator (Id, Name)
VALUES (1, 'UserType'),
(2, 'ServiceType');
INSERT INTO Enumerable (Id, EnumeratorId, Name) -- UserType
VALUES (1, 1, 'CEO'),
(2, 1, 'Manager'),
(3, 1, 'DeliveryGuy');
INSERT INTO Enumerable (Id, EnumeratorId, Name) -- ServiceDurationType
VALUES (4, 2, 'Daily'),
(5, 2, 'Weekly'),
(6, 2, 'Monthly');
CREATE TABLE [dbo].[User]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY (1,1),
[Type] INT NOT NULL FOREIGN KEY REFERENCES Enumerable(Id)
)
CREATE TABLE [dbo].[Service]
(
[Id] INT NOT NULL PRIMARY KEY IDENTITY (1,1),
[Type] INT NOT NULL FOREIGN KEY REFERENCES Enumerable(Id)
)
The questions are:
Is it viable to resolve enumerators and enumerables with 2 tables and with before update and before insert triggers, or is it more trouble than it's worth?
Is there a better way to resolve this other than using before update and before insert triggers?
Is there a better way to resolve enumerators and enumerables that is not using 2 tables and triggers, nor creating a table with relations for each of them?
I ask for your wisdom as I don't have one or more big projects behind me and I didn't get a chance to create a DB like this until now.
So let's say I have these two tables...
IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='UnitsDef' AND xtype='U')
CREATE TABLE UnitsDef
(
UnitsID INTEGER PRIMARY KEY,
UnitsName NVARCHAR(32) NOT NULL,
UnitsDisplay NVARCHAR(8) NOT NULL
);
IF NOT EXISTS (SELECT * FROM sysobjects WHERE name='Dimensions' AND xtype='U')
CREATE TABLE Dimensions
(
DimID INTEGER PRIMARY KEY IDENTITY(0,1),
DimX FLOAT,
DimXUnitsID INTEGER DEFAULT 0,
DimY FLOAT,
DimYUnitsID INTEGER DEFAULT 0,
DimZ FLOAT,
DimZUnitsID INTEGER DEFAULT 0,
FOREIGN KEY (DimXUnitsID) REFERENCES UnitsDef(UnitsID),
FOREIGN KEY (DimYUnitsID) REFERENCES UnitsDef(UnitsID),
FOREIGN KEY (DimZUnitsID) REFERENCES UnitsDef(UnitsID)
);
I'll insert data into the first table similar to this...
INSERT INTO UnitsDef (UnitsID, UnitsName, UnitsDisplay) VALUES (0, 'inch', 'in.');
INSERT INTO UnitsDef (UnitsID, UnitsName, UnitsDisplay) VALUES (1, 'millimeter', 'mm');
INSERT INTO UnitsDef (UnitsID, UnitsName, UnitsDisplay) VALUES (2, 'degree', '°');
Am I going about this the right way? This is a simplified version of the problem, but I need to know which unit each measurement is given in. Is there a better design practice for this type of situation?
How would I handle the ON DELETE and ON UPDATE for these foreign keys? If I try to cascade deletes and updates, SQL Server would not be so happy about that.
Your method is pretty good. I would make the suggestion right off that UnitsId be an identity column, so it gets incremented. Your inserts would then be:
INSERT INTO UnitsDef (UnitsName, UnitsDisplay) VALUES ('inch', 'in.');
INSERT INTO UnitsDef (UnitsName, UnitsDisplay) VALUES ('millimeter', 'mm');
INSERT INTO UnitsDef (UnitsName, UnitsDisplay) VALUES ('degree', '°');
You should also make the string columns unique in UnitsDef and give them case-sensitive collations. After all, Ml and ml are two different things ("M" is mega and "m" is milli).
You might also want to combine the units and values into a single type. This has positives and negatives. For me it adds overhead, but it can help if you want to support a fuller algebra of types.
I have a sample table like below where Course Completion Status of a Student is being stored:
Create Table StudentCourseCompletionStatus
(
CourseCompletionID int primary key identity(1,1),
StudentID int not null,
AlgorithmCourseStatus nvarchar(30),
DatabaseCourseStatus nvarchar(30),
NetworkingCourseStatus nvarchar(30),
MathematicsCourseStatus nvarchar(30),
ProgrammingCourseStatus nvarchar(30)
)
Insert into StudentCourseCompletionStatus Values (1, 'In Progress', 'In Progress', 'Not Started', 'Completed', 'Completed')
Insert into StudentCourseCompletionStatus Values (2, 'Not Started', 'In Progress', 'Not Started', 'Not Applicable', 'Completed')
Now as part of normalizing the schema I have created two other tables - CourseStatusType and Status for storing the Course Status names and Status.
Create Table CourseStatusType
(
CourseStatusTypeID int primary key identity(1,1),
CourseStatusType nvarchar(100) not null
)
Insert into CourseStatusType Values ('AlgorithmCourseStatus')
Insert into CourseStatusType Values ('DatabaseCourseStatus')
Insert into CourseStatusType Values ('NetworkingCourseStatus')
Insert into CourseStatusType Values ('MathematicsCourseStatus')
Insert into CourseStatusType Values ('ProgrammingCourseStatus')
Insert into CourseStatusType Values ('OperatingSystemsCourseStatus')
Insert into CourseStatusType Values ('CompilerCourseStatus')
Create Table Status
(
StatusID int primary key identity(1,1),
StatusName nvarchar (100) not null
)
Insert into Status Values ('Completed')
Insert into Status Values ('Not Started')
Insert into Status Values ('In Progress')
Insert into Status Values ('Not Applicable')
The modified table is as below:
Create Table StudentCourseCompletionStatus1
(
CourseCompletionID int primary key identity(1,1),
StudentID int not null,
CourseStatusTypeID int not null CONSTRAINT [FK_StudentCourseCompletionStatus1_CourseStatusType] FOREIGN KEY (CourseStatusTypeID) REFERENCES dbo.CourseStatusType (CourseStatusTypeID),
StatusID int not null CONSTRAINT [FK_StudentCourseCompletionStatus1_Status] FOREIGN KEY (StatusID) REFERENCES Status (StatusID),
)
I have few question on this:
Is this the correct way to normalize it ? The old table was very helpful to get data easily - I can store a student's course status in a single row, but now 5 rows are required. Is there a better way to do it?
Moving the data from the old table to this new table seems to be not an easy task. Can I achieve this using a query or I have to manually to do this ?
Any help is appreciated.
vou could also consider storing results in flat table like this:
studentID,courseID,status
1,1,"completed"
1,2,"not started"
2,1,"not started"
2,3,"in progress"
you will also need additional Courses table like this
courserId,courseName
1, math
2, programming
3, networking
and a students table
students
1 "john smith"
2 "perry clam"
3 "john deere"
etc..you could also optionally create a status table to store the distinct statusstrings statusstings and refer to their PK instead ofthestrings
studentID,courseID,status
1,1,1
1,2,2
2,1,2
2,3,3
... etc
and status table
id,status
1,"completed"
2,"not started"
3,"in progress"
the beauty of this representation is: it is quite easy to filter and aggregate data , i.e it is easy to query which subjects a particular person have completed, how many subjects are completed by an average student, etc. this things are much more difficult in the columnar design like you had. you can also easily add new subjects without the need to adapt your tables or even queries they,will just work.
you can also always usin SQLs PIVOT query to get it to a familiar columnar presentation like
name,mathstatus,programmingstatus,networkingstatus,etc..
but now 5 rows are required
No, it's still just one row. That row simply contains identifiers for values stored in other tables.
There are pros and cons to this. One of the main reasons to normalize in this way is to protect the integrity of the data. If a column is just a string then anything can be stored there. But if there's a foreign key relationship to a table containing a finite set of values then only one of those options can be stored there. Additionally, if you ever want to change the text of an option or add/remove options, you do it in a centralized place.
Moving the data from the old table to this new table seems to be not an easy task.
No problem at all. Create your new numeric columns on the data table and populate them with the identifiers of the lookup table records associated with each data table record. If they're nullable, you can make them foreign keys right away. If they're not nullable then you need to populate them before you can make them foreign keys. Once you've verified that the data is correct, remove the old de-normalized columns. Done.
In StudentCourseCompletionStatus1 you still need 2 associations to Status and CourseStatusType. So I think you should consider following variant of normalization:
It means, that your StudentCourseCompletionStatus would hold only one CourseStatusID and another table CourseStatus would hold the associations to CourseType and Status.
To move your data you can surely use a query.
I have 3 data tables to update database
Invoice table, primary key is InvoiceNo
InvoiceProduct table, primary key is InvoiceProductNo and foreign key InvoiceNo
InvoiceProductExp table, primary key is InvoiceProductExpNo and foreign keys are InvoiceNo and InvoiceProductNo
Facts:
One InvoiceNo has many InvoiceProductNo
one InvoiceProductNo has many InvoiceProductExpNo
3 Data Tables data entry would be for example is
Invoice (InvoiceNo,...)
(0001,...)
InvoiceProduct (InvoiceProductNo, InvoiceNo)
(1,0001,...)
(2,0001,...)
InvoiceProductExp (InvoiceProductExpNo,InvoiceProductNo,InvoiceNo)
(1,1,0001,...)
(2,1,0001,...)
(3,2,0001,...)
(4,2,0001,...)
The problem is I liked to use SQL Server generated Identity column for all primary keys of 3 tables
How can I prepare for insert statements?
Insert Into InvoiceProductExp values (auto_number, ?, ?)
How can I get InvoiceProductNo to insert into InvoiceProductExp table since InvoiceProductNo is auto number?
You're looking for SCOPE_IDENTITY()
DECLARE #InvoiceNo INT
DECLARE #InvoiceProductNo INT
INSERT INTO Invoice ([Date])
VALUES (GETDATE())
SELECT #InvoiceNo = SCOPE_IDENTITY()
INSERT INTO InvoiceProduct([InvoiceNo])
VALUES (#InvoiceNo)
SELECT #InvoiceProductNo = SCOPE_IDENTITY()
INSERT INTO InvoiceProductExp ([InvoiceProductNo], [InvoiceNo])
VALUES (#InvoiceProductNo, #InvoiceNo)
Here is SQLFiddle demo
If your primary keys are of identity column type then you don't have to insert a value into the primary key column. The identity column will auto populate when the row is committed to the database.
Does this resolve your question?
Why must manually? You can set your ID as automatically auto increment.
When you create table:
UserID INT IDENTITY(1,1) NOT NULL
sample (create the table)
CREATE TABLE dbo.Tool(
UserID INT IDENTITY NOT NULL PRIMARY KEY,
Name VARCHAR(40) NOT NULL
)
Inserting values
INSERT INTO dbo.Tool(Name) VALUES ('Person 1')
INSERT INTO dbo.Tool(Name) VALUES ('Person 2')
I've created a insert stored procedure with two tables like in the exapmle:
Table NameAge
CREATE TABLE [dbo].[Assignment3_NameAge]
(
userID int PRIMARY KEY IDENTITY(1,1),
Name varchar(255) NOT NULL,
Age int NOT NULL
)
Table Hobbies
CREATE TABLE [dbo].[Assignment3_Hobbies]
(
hobbiesID int Identity(1,1) Primary Key,
userID int Foreign Key references Assignment3_NameAge(userID),
hobbies varchar(255) NOT NULL,
)
Insert Stored Procedure
CREATE PROCEDURE [dbo].p_Assignment3Join_ins
#Name nvarchar(100),
#Age int,
#Hobbies nvarchar(100)
AS
INSERT INTO [TABLE].[dbo].[Assignment3_NameAge]
([Name]
,[Age])
VALUES (#Name,#Age)
INSERT INTO [TABLE].[dbo].[Assignment3_Hobbies]
([Hobbies])
VALUES (#Hobbies)
The problem is that when i run the stored procedure the table Hobbies has a null value for userid(the foreign key)
What am i doing wrong?
You should provide the key of the Assignment3_NameAge value you want to insert into Assignment3_Hobbies.
If you want the last inserted you can use SCOPE_IDENTITY() from SQL Server(if you're using SQL Server) or equivalent. It will give you the last inserted value from Assignment3_NameAge
I am guessing this is SQL Server based on the IDENTITY column. Correct?
The first insert creates a user, but there is no user ID being set on the insert of the hobby. You need to capture the identity value from the first insert to be used in the second insert. Have you gon over the system functions available?
You're not supplying a value for it, SQL won't automagically fill the value in for you even though you've created a Foreign Key relationship. It's your job to populate the tables.