Cannot insert the value NULL into column 'id', even though Column has IDENTITY property - sql

CREATE TABLE Type1
(
TypeID TINYINT NOT NULL IDENTITY(1,1),
TypeName VARCHAR(20) NOT NULL,
Speed VARCHAR(10) NOT NULL
CONSTRAINT TypeID_pk PRIMARY KEY (TypeID)
);
CREATE TABLE Splan
(
PlanID TINYINT NOT NULL IDENTITY(1,1),
TypeID TINYINT NOT NULL,
PlanName VARCHAR(20) NOT NULL,
Quota SMALLINT NOT NULL
CONSTRAINT PlanID_pk PRIMARY KEY (PlanID)
CONSTRAINT TypeID_fk FOREIGN KEY (TypeID) REFERENCES Type1(TypeID)
);
INSERT INTO Type1(TypeName, Speed)
VALUES ('Sample type', '10Mbps'),
('Other type', '50Mbps');
^Up until there its fine
and then when I enter the following it returns "Msg 515, Level 16, State 2, Line 8
Cannot insert the value NULL into column 'TypeID' ..... column does not allows. INSERT fails." Statement terminates
INSERT INTO Splan(PlanName, Quota)
VALUES ('Some sample name', '500GB'),
('sample2, '250GB');
I've tried creating the constraints at both column and table level but the second INSERT statement still refused to enter. Double checked via the GUI and 'TypeID' definitely has an IDENTITY property.
I've looked about everywhere and this errors seems to stem from the lack of an IDENTITY property, yet its present in my creation statements and the error still comes up. Tried removing the seed and increment from IDENTITY, still nothing. Also tried inserting the data one row at a time, nothing there either.
P.S If you haven't noticed the actual names have been substituted and other columns rows have been omitted.

Since you created typID as NOT NULL, Sql is complaining that the default value (NULL) is not acceptable.
Try
INSERT INTO Splan(TypeID, PlanName, Quota)
VALUES (1, 'Some sample name', '500GB'),
(2, 'sample2, '250GB');
Where corresponding records with TypeID = 1 and TypeID = 2 are in your Type1 table.
You are creating 2 tables: Type1 which has a primary key TypeId that is auto generated
and SPlan which has a primary key PlanId that is also auto generated and a foreign key TypeId that must be supplied and cannot be null.
As written you must enter 1 or more records into Type1 first, obtain their TypeIds, then enter those TypeIds into new records in SPlan.
Incidentally, using TINYINT for your primary key data types is perfectly legal but probably a really bad idea if this is anything other than homework.

You need to supply a value for TypeID in your second query because you have a foreign key relationship with the Type1 table and because the TypeID column in the Splan table is also declared NOT NULL.
INSERT INTO Splan(TypeID, PlanName, Quota)
VALUES (1, 'Some sample name', '500GB'),
(2, 'sample2, '250GB');
Try inserting both records in a transaction using SCOPE_IDENTITY
begin tran
INSERT INTO Type1(TypeName, Speed)
VALUES ('Sample type', '10Mbps')
DECLARE #id INT = SCOPE_IDENTITY();
INSERT INTO Splan(TypeID, PlanName, Quota)
VALUES (#id, 'Some sample name', '500GB')
commit

Related

How do I select insert into select a table which already has values in the primary key column without adding new rows?

I'm working on a database for my school project in which I have to produce a functional database by normalizing sample tables given to us.
One table I'm having trouble with is itineraries. I produce 3 tables from the normalization which are "Destinations", "Itineraries" and "Itinerary_Destinations".
The code for Destinations is:
create table Destinations
(
DestinationID varchar(5) primary key,
Name varchar(45)
);
The code for Itineraries is:
create table Itineraries
(
ItineraryID varchar(5),
Name varchar(45)
);
The code for the last table is:
create table Itinerary_Destinations
(
DI varchar(5) primary key,
ItineraryID varchar(5) foreign key references Itineraries(ItineraryID),
Itinerary_Name varchar(45),
DestinationID varchar(5) foreign key references Destinations(DestinationID),
Destination_Name varchar(45)
);
Data has already been inserted into all 3 tables with the exception of 'Destination_Name' and 'Itinerary_Name' columns. The code I'm attempting to use is returning as error. The code is shown below.
insert into Itinerary_Destinations (Itinerary_name)
select Name from Itineraries where
Itineraries.ItineraryID = ItineraryID;
The error it returns is
Msg 515, Level 16, State 2, Line 1 Cannot insert the value NULL into
column 'DI', table 'DDDAssignment.dbo.Itinerary_Destinations'; column
does not allow nulls. INSERT fails. The statement has been terminated.
Is there a method to accomplish the task of inserting the Destination_Name and Itinerary_Name without creating new records that require primary keys?
Or should I do it manually?
If you want to modify records which already exist, then you should be using an UPDATE rather than an INSERT:
UPDATE a
SET Itinerary_name = b.Name
FROM Itinerary_Destinations a
INNER JOIN Itinerary_name b
ON a.ItineraryID = b.ItineraryID;
But, if you do have some data which is not already logically associated with the Itinerary_Destinations table, then using an insert is appropriate.
use coalesce funtion in case null it will insert blank string, as your column does not allow null value thats why you got that error in your query
insert into Itinerary_Destinations (Itinerary_name)
select coalesce(Name,' ') from Itineraries where
Itineraries.ItineraryID = ItineraryID;

How to insert value into foreign key in SQL server? (Avoid the duplicate key.)

I create two table. They connected by primary key and foreign key. When I insert new values, it said cannot insert duplicate key in object. Here are my tables
create table person (
sinNum int primary key not null,
gender varchar(6) not null check (gender in ('male','female')) default 'female',
age int not null check (age>=18 and age<=100),
emailAddr varchar (50) not null,
phoneNum int not null,
)
create table employee (
empId int identity (1,1) unique,
lastName varchar (30) not null,
firstName varchar (30) not null,
sinNum int unique foreign key references person (sinNum),
departmentId int foreign key references department (departmentId),
position varchar (20) not null check (position in ('clerk','assistant','supervisor','manager','director','president')) default'clerk',
baseSalary float not null
)
Here are my insert statements
insert into person (sinNum,gender,age,emailAddr, phoneNum) values (333,
'female', 24, 'dds', 2121)
insert into employee(lastName,firstName, sinNum, departmentId,
position,baseSalary) values ('Snow','John',333,20,'clerk',4000)
Here are the error messages
Violation of PRIMARY KEY constraint 'PK__person__228E26BE3A9512B2'.
Cannot insert duplicate key in object 'dbo.person'. The duplicate key
value is (333).
Can anyone show me the way please? Many thanks
You have not set sinNum as identity. Make it auto incremented and then change your insert query as below.
insert into person (sinNum,gender,age,emailAddr, phoneNum) values ((SELECT ISNULL(MAX(sinNum)+1,0) FROM person WITH(SERIALIZABLE, UPDLOCK)),
'female', 24, 'dds', 2121)
You can use simpler version also, but it doesn't guarantee concurrency:
insert into person (sinNum,gender,age,emailAddr, phoneNum) values (NULL,
'female', 24, 'dds', 2121)
Since sinNum is your primary key, if you try to INSERT a new row containing the same value it will reject you.
Just use the following query to delete the rows before adding it again.
DELETE FROM person WHERE sinNum = 333;
You can also update/merge the row or simply not add it, since you have done it already.
As the column 'sinum' is primary key, you can't define it explicitly.
So please have a try with below.
Insert into person (gender,age,emailAddr, phoneNum) values ( 'female', 24, 'dds', 2121)
Declare #sinnum=IDENT_CURRENT('Person')
If ##error=0
Insert into employee(lastName,firstName, sinnum, departmentId, position,baseSalary) values ('Snow','John',#sinnum,20,'clerk',4000)
Ident_current will save the last inserted primary key value in the mentioned table. Saving that value in a temporary variable, inorder to use the same value as FK in the employee table.
##error used here to ensure insert on employee table only on successful insert made in person table.
What's happening here is that your insert on Person table is violating the primary key constraint. So we can use this exception as an antidote.
You can make use of Try-Catch statement and can implement your further logic in the catch block.
/* You an use #output parameter too */
Declare #output bit=1
BEGIN TRY
insert into person (sinNum,gender,age,emailAddr, phoneNum) values (333,
'female', 24, 'dds', 2121)
insert into employee(lastName,firstName, sinNum, departmentId,
position,baseSalary) values ('Snow','John',333,20,'clerk',4000)
print 'Record inserted in both table'
set #output=1
END TRY
BEGIN CATCH
if error_message() like 'Violation of PRIMARY KEY constraint%'
Begin
/* Do whatever you like to do here */
/* You can delete the existing record if you want */
print 'Record already exists is Person table' --just the intimation
set #output=0
End
else
print 'other exception' --just the intimation
END CATCH
You can delete the existing record in catch block or can make new transaction using #output variable.. Hope it works for you.

How to use value generated by GENERATE_UNIQUE() function as foreign key?

I trying to implement the example from this manual Generating Unique Values in DB2 Universal Database but encountered the following problem.
I've two tables,
CREATE TABLE PC_LIST (
PC_ID CHAR(13) FOR BIT DATA NOT NULL,
PC_NAME VARCHAR(100) NOT NULL
PRIMARY KEY (ID)
);
And second table
CREATE TABLE PC_DATA (
ID CHAR(13) FOR BIT DATA NOT NULL,
PC_ID CHAR(13) FOR BIT DATA NOT NULL,
PC_NAME VARCHAR(100) NOT NULL
PRIMARY KEY (ID),
FOREIGN KEY (PC_ID) REFERENCES PC_LIST(PC_ID)
);
I add records to first table PC_LIST without any issues, and use inside INSERT query GENERATE_UNIQUE() function, everything works fine.
When I try to add a record to the second table and copy a value from PC_LIST.PC_ID as is I get an error Value "20150408131401000109000000 " is too long..
When I added a cast like following: CAST('20150408131401000109000000' AS CHAR(13) FOR BIT DATA) I get an error that The INSERT or UPDATE value of the FOREIGN KEY is not equal to any value of the parent key of the parent table.
What am I doing wrong?
Thank you.
UPDATE:
This code I use to insert data in PC_DATA
INSERT INTO PC_DATA
(
ID,
PC_ID,
PC_NAME
) VALUES (GENERATE_UNIQUE(), CAST('20150408131401000109000000' AS CHAR(13) FOR BIT DATA) ,'anatoly-pc');
Of course that PC_ID I've taken from PC_LIST table where it exists.

Foreign Key is null when insert using Stored Procedure

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.

Ensuring uniqueness of multiple large URL fields in MS SQL

I have a table with the following definition:
CREATE TABLE url_tracker (
id int not null identity(1, 1),
active bit not null,
install_date int not null,
partner_url nvarchar(512) not null,
local_url nvarchar(512) not null,
public_url nvarchar(512) not null,
primary key(id)
);
And I have a requirement that these three URLs always be unique - any individual URL can appear many times, but the combination of the three must be unique (for a given day).
Initially I thought I could do this:
CREATE UNIQUE INDEX uniques ON url_tracker
(install_date, partner_url, local_url, public_url);
However this gives me back the warning:
Warning! The maximum key length is 900 bytes. The index 'uniques' has maximum
length of 3076 bytes. For some combination of large values, the insert/update
operation will fail.
Digging around I learned about the INCLUDE argument to CREATE INDEX, but according to this question converting the command to use INCLUDE will not enforce uniqueness on the URLs.
CREATE UNIQUE INDEX uniques ON url_tracker (install_date)
INCLUDE (partner_url, local_url, public_url);
How can I enforce uniqueness on several relatively large nvarchar fields?
Resolution
So from the comments and answers and more research I'm concluding I can do this:
CREATE TABLE url_tracker (
id int not null identity(1, 1),
active bit not null,
install_date int not null,
partner_url nvarchar(512) not null,
local_url nvarchar(512) not null,
public_url nvarchar(512) not null,
uniquehash AS HashBytes('SHA1',partner_url+local_url+public_url) PERSISTED,
primary key(id)
);
CREATE UNIQUE INDEX uniques ON url_tracker (install_date,uniquehash);
Thoughts?
I would make a computed column with the hash of the URLs, then make a unique index/constraint on that. Consider making the hash a persisted computed column. It shouldn't have to be recalculated after insertion.
Following the ideas from the conversation in the comments. Assuming that you can change the datatype of the URL to be VARCHAR(900) (or NVARCHAR(450) if you really think you need Unicode URLs) and be happy with the limitation on the length of the URL, this solution could work. This also assumes SQL Server 2008 or better. Please, always specify what version you're working with; sql-server is not specific enough, since solutions can vary greatly depending on the version.
Setup:
USE tempdb;
GO
CREATE TABLE dbo.urls
(
id INT IDENTITY(1,1) PRIMARY KEY,
url VARCHAR(900) NOT NULL UNIQUE
);
CREATE TABLE dbo.url_tracker
(
id INT IDENTITY(1,1) PRIMARY KEY,
active BIT NOT NULL DEFAULT 1,
install_date DATE NOT NULL DEFAULT CURRENT_TIMESTAMP,
partner_url_id INT NOT NULL REFERENCES dbo.urls(id),
local_url_id INT NOT NULL REFERENCES dbo.urls(id),
public_url_id INT NOT NULL REFERENCES dbo.urls(id),
CONSTRAINT unique_urls UNIQUE
(
install_date,partner_url_id, local_url_id, public_url_id
)
);
Insert some URLs:
INSERT dbo.urls(url) VALUES
('http://msn.com/'),
('http://aol.com/'),
('http://yahoo.com/'),
('http://google.com/'),
('http://gmail.com/'),
('http://stackoverflow.com/');
Now let's insert some data:
-- succeeds:
INSERT dbo.url_tracker(partner_url_id, local_url_id, public_url_id)
VALUES (1,2,3), (2,3,4), (3,4,5), (4,5,6);
-- fails:
INSERT dbo.url_tracker(partner_url_id, local_url_id, public_url_id)
VALUES(1,2,3);
GO
/*
Msg 2627, Level 14, State 1, Line 3
Violation of UNIQUE KEY constraint 'unique_urls'. Cannot insert duplicate key
in object 'dbo.url_tracker'. The duplicate key value is (2011-09-15, 1, 2, 3).
The statement has been terminated.
*/
-- succeeds, since it's for a different day:
INSERT dbo.url_tracker(install_date, partner_url_id, local_url_id, public_url_id)
VALUES('2011-09-01',1,2,3);
Cleanup:
DROP TABLE dbo.url_tracker, dbo.urls;
Now, if 900 bytes is not enough, you could change the URL table slightly:
CREATE TABLE dbo.urls
(
id INT IDENTITY(1,1) PRIMARY KEY,
url VARCHAR(2048) NOT NULL,
url_hash AS CONVERT(VARBINARY(32), HASHBYTES('SHA1', url)) PERSISTED,
CONSTRAINT unique_url UNIQUE(url_hash)
);
The rest doesn't have to change. And if you try to insert the same URL twice, you get a similar violation, e.g.
INSERT dbo.urls(url) SELECT 'http://www.google.com/';
GO
INSERT dbo.urls(url) SELECT 'http://www.google.com/';
GO
/*
Msg 2627, Level 14, State 1, Line 1
Violation of UNIQUE KEY constraint 'unique_url'. Cannot insert duplicate key
in object 'dbo.urls'. The duplicate key value is
(0xd111175e022c19f447895ad6b72ff259552d1b38).
The statement has been terminated.
*/