Insert Values with foreign keys SQL - sql-server

I am trying to insert data that has foreign keys. I am able to update the first two tables with the GUID but I am not able to do so in the last 3 tables I am trying to update
BEGIN TRANSACTION;
DECLARE #myid uniqueidentifier
SET #myid = NEWID()
INSERT INTO [SERVER].[DB].[Pod] (id)
VALUES (#myid)
INSERT INTO [SERVER].[DB].[RackPattern] ([id])
VALUES (#myid)
INSERT INTO [SERVER].[DB].[PhysicalServer] ([serialNumber], [rackPosition],[Rack_id], id)
VALUES ('2327', '25', 'DBedc1001r01', #myid)
INSERT INTO [SERVER].[DB].[Rack] ([Site_id], [Pod_id], [RackPattern_id], id)
VALUES ('Datacenter','PostionID', 'RACK_PATTERN_ID_1', #myid)
INSERT INTO [SERVER].[DB].[Site] (Pod_id, id)
VALUES ('PostionID', #myid)
COMMIT;
Results:
(1 row(s) affected)
(1 row(s) affected)
Msg 547, Level 16, State 0, Line 11
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__PhysicalS__Rack___00DF2177". The conflict occurred in database "VCO01-A_PATTERN_DB", table "DB.Rack", column 'id'.
Msg 547, Level 16, State 0, Line 14
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Rack__Site_id__6BE40491". The conflict occurred in database "VCO01-A_PATTERN_DB", table "DB.Site", column 'id'.
Msg 547, Level 16, State 0, Line 17
The INSERT statement conflicted with the FOREIGN KEY constraint "FK__Site__Pod_id__4F47C5E3". The conflict occurred in database "VCO01-A_PATTERN_DB", table "DB.Pod", column 'id'.

Well, you insert something into PhysicalServer in your third statement, which references Rack with a specific ID - but the insert into the Rack table only happens in the fourth statement - so that Rack.Id isn't going to be there (yet) when you run your third SQL statement! Same for the fifth statement - you insert a Site with an id - but you already reference that table in your fourth statement....
It's just a matter of inserting in the RIGHT order here - try this:
BEGIN TRANSACTION;
DECLARE #myid uniqueidentifier
SET #myid = NEWID()
INSERT INTO [SERVER].[DB].[Pod] (id)
VALUES (#myid)
INSERT INTO [SERVER].[DB].[RackPattern] ([id])
VALUES (#myid)
-- insert into SITE
INSERT INTO [SERVER].[DB].[Site] (Pod_id, id)
VALUES ('PostionID', #myid)
-- insert into RACK, referencing the SITE
INSERT INTO [SERVER].[DB].[Rack] ([Site_id], [Pod_id], [RackPattern_id], id)
VALUES ('Datacenter', 'PostionID', 'RACK_PATTERN_ID_1', #myid)
-- NOW you can insert into "PhysicalServer" which references the rack ...
INSERT INTO [SERVER].[DB].[PhysicalServer] ([serialNumber], [rackPosition],[Rack_id], id)
VALUES ('2327', '25', 'DBedc1001r01', #myid)
COMMIT;
But there's still something fishy.....
In the third statement you insert something into Site with an id that's this GUID you created. Yet in the fourth statement, you reference the SiteId as 'Datacenter' ...... something isn't right yet.....

Related

SQL Server trigger does not recognize inserted row

I have simple SQL Server trigger and for some reason it does not recognize INSERTED row.
Here is code:
-- code
DROP TABLE a;
GO
CREATE TABLE a
(
id INT IDENTITY(1,1) PRIMARY KEY,
v INT
)
GO
DROP TABLE a_audit;
CREATE TABLE a_audit
(
id INT,
v INT,
[updated_at] [DATETIME] NOT NULL DEFAULT GETDATE()
)
GO
CREATE TRIGGER [dbo].[trg_a]
ON [dbo].[a]
AFTER INSERT, UPDATE, DELETE
NOT FOR REPLICATION
AS
BEGIN
SET NOCOUNT ON;
PRINT 'start';
DECLARE #xmltmp xml = (SELECT * FROM inserted FOR XML AUTO);
PRINT CONVERT(NVARCHAR(MAX), #xmltmp);
-- INSERT INTO a_audit (id, v) VALUES (inserted.id, inserted.v);
END;
GO
INSERT INTO a (v)
VALUES (1);
WAITFOR DELAY '00:00:01.11';
INSERT INTO a (v)
VALUES (2);
GO
SELECT * FROM a;
PRINT 'done'
It produces this output
start
<inserted id="1" v="1"/>
(1 row affected)
start
<inserted id="2" v="2"/>
(1 row affected)
(2 rows affected)
done
So I see that INSERTED row does exist.
However, if I remove comment on insert statements the output is this:
Msg 4104, Level 16, State 1, Procedure trg_a, Line 14 [Batch Start Line 16]
The multi-part identifier "inserted.id" could not be bound.
Msg 4104, Level 16, State 1, Procedure trg_a, Line 14 [Batch Start Line 16]
The multi-part identifier "inserted.v" could not be bound.
What is wrong?
inserted is a table, not a function. To INSERT from another table you need to use a INSERT INTO... SELECT ... FROM statement:
INSERT INTO a_audit (id,v)
SELECT id,
v
FROM inserted;
You can't reference a table's columns unless you use a FROM. For example just running the below would give the error below:
SELECT a_audit.id, a.audit.v;
The multi-part identifier "a_audit.id" could not be bound.
You would have to a SELECT...FROM:
SELECT id, v
FROM a_audit;

Why am I getting error 8101 when writing a stored procedure?

I have the table called Sales
CREATE TABLE Sales
(
SaleID int IDENTITY(1,1) PRIMARY KEY
,DateOfTransaction dateTime NOT NULL
,QuantitySold int NOT NULL
,PaymentMethod nvarchar(40) NOT NULL
,EquipmentID int FOREIGN KEY REFERENCES Equipments(EquipmentID)
,CustomerID int FOREIGN KEY REFERENCES Customers(CustomerID)
,SalespersonID int FOREIGN KEY REFERENCES Salespersons(SalespersonID)
);
I am writing a stored procedure in which I want to insert the data. This is my code so far:
CREATE PROCEDURE dbo.sproc_PurchaseAdd
#SaleID INT OUTPUT
,#DateOfTransaction dateTime
,#QuantitySold int
,#PaymentMethod nvarchar(40)
,#EquipmentId int
,#CustomerID int
,#SalesPersonId int
AS
BEGIN
SET IDENTITY_INSERT Sales ON
INSERT INTO Sales
VALUES (#DateOfTransaction, #QuantitySold, #PaymentMethod, #EquipmentId, #CustomerID, #SalesPersonId)
SET #SaleID = ##IDENTITY
END
GO
But I am getting an error:
Msg 8101, Level 16, State 1, Procedure sproc_PurchaseAdd, Line 13 [Batch Start Line 75]
An explicit value for the identity column in table 'Sales' can only be specified when a column list is used and IDENTITY_INSERT is ON.
Is there any specific thing I am missing? Please help me out
SaleID is IDENTITY so it wll auto increment,
you don't need this:
SET IDENTITY_INSERT Sales ON
This is ok:
INSERT INTO Sales VALUES (#DateOfTransaction,#QuantitySold,#PaymentMethod,#EquipmentId,#CustomerID,#SalesPersonId)
If this will not work, try to specify columns:
INSERT INTO Sales (DateOfTransaction,QuantitySold,PaymentMethod,EquipmentID,CustomerID,SalespersonID) VALUES (#DateOfTransaction,#QuantitySold,#PaymentMethod,#EquipmentId,#CustomerID,#SalesPersonId)
Also try to use SCOPE_IDENTITY() instead ##IDENTITY

SQL Server Insert Null error in spite of providing not null values

I am trying to do an insert but it is giving an error stating that credits cannot be null but I am not providing null. Attached Screenshot
Code: Insert into [dbo].[Course] values (12,'Java',1,1,1);
Error: Msg 515, Level 16, State 2, Procedure trgAfterInsert, Line 31
Cannot insert the value NULL into column 'Credits', table 'DemoCollege.dbo.Course'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Trigger:
Create trigger trgAfterInsert2 ON [dbo].[Course]
After Insert
AS
Declare #cid int;
Declare #cname nvarchar(50);
Select #cid = i.CourseID from inserted i;
Select #cname = i.Title from inserted i;
Insert into dbo.CourseTemp values (#cid, #cname);
Print 'After insert trigger fired';
GO
There's an insert trigger on the table & that's where the error is being generated from.
There must be some logic in that is converting the provided credit value to a null value somehow.
Just provide the columns where you want to insert the values.
Insert into [dbo].[Course](ColName1, ColName2, ColName3, ColName4, etc..) values (12,'Java',1,1,1);
Most probably you're missing a col in the middle

Error in Insert into database in Stored Procedure

I have a problem with this code :
ALTER PROCEDURE [arch].[spInsertToDocumentFileCategoryRelation]
#DocumentNumber nvarchar(50)
,#DocumentDate date
,#IsDocumentDelete bit
,#Address nvarchar(max)
,#DocumentLevelTypeId int
,#DocumentId2 bigint
,#DocumentRelationTypeId tinyint
,#CategoryId bigint
,#FileId bigint
,#FileAssignCategoryId bigint OUTPUT
,#DocumentRelationId bigint OUTPUT
,#FileOfDocumentId bigint OUTPUT
,#DocumentId bigint OUTPUT
AS
BEGIN
INSERT INTO [arch].[Document]
(
[DocumentNumber]
,[DocumentDate]
,[DateOfDocumentCreate]
,[IsDocumentDelete]
,[Address]
,[DocumentLevelTypeId]
)
VALUES
(
#DocumentNumber
,#DocumentDate
,'2015-5-12'
,#IsDocumentDelete
,#Address
,#DocumentLevelTypeId
)
Set #DocumentId = SCOPE_IDENTITY();
INSERT INTO [arch].[FileOfDocument]
(
[DocumentId]
,[FileId]
)
VALUES
(
#DocumentId
,#FileId
)
Set #FileOFDocumentId = SCOPE_IDENTITY();
INSERT INTO [arch].[DocumentRelation]
(
[DocumentRelationTypeId]
,[DocumentId1]
,[DocumentId2]
)
VALUES
(
#DocumentRelationTypeId
,#DocumentId
,#DocumentId2
)
Set #DocumentRelationId = SCOPE_IDENTITY();
INSERT INTO [arch].[FileAssignCategory]
(
[CategoryId]
,[FileId]
)
VALUES
(
#CategoryId
,#FileId
)
Set #FileAssignCategoryId = SCOPE_IDENTITY();
END
this code Execute correctly but when I want to test this Stored Procedure with some input values, sql server report some errors :
Msg 515, Level 16, State 2, Procedure
spInsertToDocumentFileCategoryRelation, Line 27
Cannot insert the value NULL into column 'DocumentTypeId', table
'ffisherDB.arch.Document'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Msg 515, Level 16, State 2, Procedure
spInsertToDocumentFileCategoryRelation, Line 48
Cannot insert the value NULL into column 'DocumentId', table
'ffisherDB.arch.FileOfDocument'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Msg 515, Level 16, State 2, Procedure
spInsertToDocumentFileCategoryRelation, Line 61
Cannot insert the value NULL into column 'DocumentId1', table
'ffisherDB.arch.DocumentRelation'; column does not allow nulls. INSERT
fails.
The statement has been terminated.
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
I have four Key that set with SCOPE_IDENTITY(). the first one set exactly right but the others fails and above Errors report.
please help me.
Well, from error text it looks like your arch.Document table has non-nullable column DocumentTypeId.
And you're not filling that column here:
INSERT INTO [arch].[Document]
(
[DocumentNumber]
,[DocumentDate]
,[DateOfDocumentCreate]
,[IsDocumentDelete]
,[Address]
,[DocumentLevelTypeId]
)
So this column has its default value (I guess it is null), thus this insert fails, thus #DocumentId is null and remaining inserts fails too...
As per first error message DocumentTypeId field in Document table is not allowing null. You should insert a value into it in the insert query.
Change your insert to
INSERT INTO [arch].[Document]
(
[DocumentNumber]
,[DocumentDate]
,[DateOfDocumentCreate]
,[IsDocumentDelete]
,[Address]
,[DocumentLevelTypeId]
,[DocumentTypeId] --Add document type id here
)
VALUES
(
#DocumentNumber
,#DocumentDate
,'2015-5-12' --You better insert a DATE type or in ISO formatted 'yyyymmdd' string.
,#IsDocumentDelete
,#Address
,#DocumentLevelTypeId
,#DocumentTypeId --Insert a non - null value
)
Second & third error messages are due to first error.

SQL Server check constraint failing on correct input

I'm using a check constraint on a table to restrict what values are inserted in the table..
Here's an explanation of what I'm trying to do
If any Product(sedan) is associated to a specific ObjLevel (Toyota) then the same Product cannot be associated to another specific ObjLevel (Lexus)
After I apply the check constraint on the table, any insert containing ObjLevel "toyota" or "lexus" fails..
create table ObjLevel(
OLID int identity,
Name varchar(50) not null
)
insert into ObjLevel values('Ford')
insert into ObjLevel values('Toyota')
insert into ObjLevel values('Lexus')
insert into ObjLevel values('GM')
insert into ObjLevel values('Infiniti')
create table ObjInstance(
OLIID int identity (20,1),
OLID int
)
insert into ObjInstance values(1)
insert into ObjInstance values(2)
insert into ObjInstance values(3)
insert into ObjInstance values(4)
insert into ObjInstance values(5)
create table Product(
PID int identity(50,1),
Name varchar(20)
)
insert into Product values ('sedan')
insert into Product values ('coupe')
insert into Product values ('hatchback')
create table ObjInstanceProd(
OLIID int,
PID int
)
create FUNCTION [dbo].[fnObjProd] (#Pid int) RETURNS bit WITH EXECUTE AS CALLER AS
BEGIN
DECLARE #rv bit
DECLARE #cnt int
SET #cnt = 0
SET #rv = 0
SET #cnt=
(Select Count(*) from ObjInstanceProd olip
join ObjInstance oli
on olip.OLIID = oli.OLIID
join ObjLevel ol
on ol.OLID = oli.OLID
where ol.Name in ('Toyota','Lexus')
and PID = #Pid)
if(#cnt>0)
SET #rv = 1
RETURN #rv
END
ALTER TABLE [dbo].[ObjInstanceProd] WITH CHECK ADD CONSTRAINT [CK_OLIP] CHECK ([dbo].[fnObjProd]([PID])=0)
--Insert Statement
insert into ObjInstanceProd(OLIID,PID) values (22,51)
Msg 547, Level 16, State 0, Line 1
The INSERT statement conflicted with the CHECK constraint "CK_OLIP". The conflict occurred in database "tmp", table "dbo.ObjInstanceProd", column 'PID'.
The statement has been terminated.
--Execute Function
select [dbo].[fnObjProd] (51)
0
Initially the Table ObjInstanceProd is empty.. So, no matter what value I put in the table, as long as the function in the constraint returns a 0, it should accept it.. But it does not..
The function is correctly returning a 0 (when executed independently), but for some reason, the check constraint returns a 1
When the CHECK constraint fires, the row is already in the table. Therefore, the function is called, and since there is a row returned by the query, the function returns 1, not 0. Try this. Drop the constraint, insert your row successfully, and then run this query:
SELECT OLIID, PID, dbo.fnObjProd([PID]) FROM dbo.ObjInstanceProd;
It should return 1 for every value of PID. Try to add the constraint now. It will fail for the same reason.
Have you considered using a trigger for this? If you use a check constraint, this will turn any multi-row insert or update into a cursor behind the scenes. This can absolutely kill performance and concurrency depending on how you touch your tables. Here is a simple INSTEAD OF INSERT trigger to prevent bad values going in with a single operation, even for a multi-row insert:
CREATE TRIGGER dbo.trObjProd
ON dbo.ObjInstanceProd
INSTEAD OF INSERT AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS
(
SELECT 1 FROM inserted
WHERE EXISTS
(
SELECT 1
FROM dbo.ObjInstanceProd AS olip
INNER JOIN dbo.ObjInstance AS oli
ON olip.OLIID = oli.OLIID
INNER JOIN dbo.ObjLevel AS ol
ON ol.OLID = oli.OLID
WHERE
ol.Name in ('Toyota','Lexus')
AND olip.PID = inserted.PID
)
)
BEGIN
INSERT ObjInstanceProd(OLIID, PID)
SELECT OLIID, PID FROM inserted;
END
ELSE
BEGIN
RAISERROR('At least one value was not good.', 11, 1);
SELECT OLIID, PID FROM inserted;
END
END
GO
If you're going to stick with a function, this is a much more efficient approach, however you need to define a way to determine that the current row being inserted is excluded from the check - I couldn't determine how to do that because there are no constraints on dbo.ObjInstanceProd. Is OLIID, PID unique?
ALTER FUNCTION [dbo].[fnObjProd]
(
#Pid INT
)
RETURNS BIT
WITH EXECUTE AS CALLER
AS
BEGIN
RETURN
(
SELECT CASE WHEN EXISTS
(
SELECT 1
FROM dbo.ObjInstanceProd AS olip
INNER JOIN dbo.ObjInstance AS oli
ON olip.OLIID = oli.OLIID
INNER JOIN dbo.ObjLevel AS ol
ON ol.OLID = oli.OLID
WHERE
ol.Name in ('Toyota','Lexus')
AND olip.PID = #Pid
) THEN 1 ELSE 0 END
);
END
GO

Resources