Insert into two tables at the same time insert new record - sql

I have two SQL Server tables to work with in my database.
Here is my table VMA_VehicleDetails_TB:
CREATE TABLE [dbo].[VMA_VehicleDetails_TB]
(
[VehRegID] INT IDENTITY (1000, 2) NOT NULL,
[TraPNumber] NVARCHAR (60) NOT NULL,
[VehOwner] NVARCHAR (60) NOT NULL,
[RegExpDate] DATE NOT NULL,
[InsExpDate] DATE NOT NULL,
[VehModel] NVARCHAR (120) NOT NULL,
[VehOrigin] NVARCHAR (120) NOT NULL,
[VehType] NVARCHAR (80) NOT NULL,
PRIMARY KEY CLUSTERED ([VehRegID] ASC)
);
Here is my table VMA_VehDrvAssigned_TB:
CREATE TABLE [dbo].[VMA_VehDrvAssigned_TB]
(
[VehRegID] INT DEFAULT ((0)) NOT NULL,
[DrvRegID] INT DEFAULT ((0)) NOT NULL,
[IsAssigned] BIT DEFAULT ((0)) NOT NULL,
CONSTRAINT [PK_VMA_VehDrvAssigned_TB] PRIMARY KEY CLUSTERED ([VehRegID] ASC)
);
I have use this stored procedure to add new registered vehicle id to the VMA_VehDrvAssigned_TBtable. It is working fine.
ALTER PROCEDURE [dbo].[addNewVehicleDetail_SP]
#TraPNumber NVARCHAR (60)
,#VehOwner NVARCHAR (60)
,#RegExpDate DATE
,#InsExpDate DATE
,#VehModel NVARCHAR (120)
,#VehOrigin NVARCHAR (120)
,#VehType NVARCHAR (80)
,#IsAssigned BIT
,#DrvRegID VARCHAR(60)
AS
BEGIN
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO [VMA_VehicleDetails_TB] (TraPNumber, VehOwner, RegExpDate, InsExpDate, VehModel, VehOrigin, VehType)
VALUES (#TraPNumber, #VehOwner, #RegExpDate, #InsExpDate, #VehModel, #VehOrigin, #VehType)
INSERT INTO VMA_VehDrvAssigned_TB (VehRegID)
SELECT
VehRegID = scope_identity();
END
Now, I want to add #IsAssigned and #DrvRegID to the same table while insert new record. But, I only know to add single column to the table. Did I something wrong??

Just modify last INSERT.
ALTER PROCEDURE [dbo].[addNewVehicleDetail_SP]
-- Add the parameters for the stored procedure here
#TraPNumber NVARCHAR (60)
,#VehOwner NVARCHAR (60)
,#RegExpDate DATE
,#InsExpDate DATE
,#VehModel NVARCHAR (120)
,#VehOrigin NVARCHAR (120)
,#VehType NVARCHAR (80)
,#IsAssigned BIT
,#DrvRegID VARCHAR(60)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
INSERT INTO [VMA_VehicleDetails_TB] (TraPNumber,VehOwner,RegExpDate,InsExpDate,VehModel,VehOrigin,VehType)
VALUES (#TraPNumber,#VehOwner,#RegExpDate,#InsExpDate,#VehModel,#VehOrigin,#VehType)
INSERT INTO VMA_VehDrvAssigned_TB (VehRegID, DrvRegID, IsAssigned )
SELECT scope_identity(), #DrvRegID, #IsAssigned ;
END

Related

How to get the auto-generated primary key after insertion in stored procedure?

My SQL Server table:
[dbo].[Rep] (
[rep_ID] INT IDENTITY (300, 1) NOT NULL,
[Restaurant_ID] INT NULL,
[Fname] VARCHAR (50) NOT NULL,
[Lname] VARCHAR (50) NOT NULL,
CONSTRAINT [PK_Rep_ID] PRIMARY KEY CLUSTERED ([rep_ID] ASC),
CONSTRAINT [FK_Restaurant_ID] FOREIGN KEY ([Restaurant_ID]) REFERENCES [dbo].[Restaurants] ([ID])
);
I want to create a stored procedure that return the auto generated key for the inserted record.
My current stored procedure:
CREATE PROCEDURE [dbo].[createRepAcc]
#first varchar(50),
#last varchar(50)
AS
INSERT INTO Rep([Fname], [Lname])
OUTPUT inserted.rep_ID
VALUES (#first, #last);
It's able to insert into the table but only return 1 instead of the primary key generated.
What am I doing wrong?
You can use scope_identity() to get the last generated id. For your case here is a detailed worksheet
/* creating a simple table with identity column */
CREATE TABLE dbo.a(identity_column INT IDENTITY(300,1), x CHAR(1));
/* Procedure that inserts values and returns generated output*/
CREATE PROCEDURE [dbo].[ap]
#x char(1),
#id int output
AS
INSERT INTO a(x) VALUES (#x);
select #id = SCOPE_IDENTITY();
/* This is how the procedure could be called */
declare #ident int -- declare a variable to receive output
execute dbo.ap #x='b', #id=#ident output -- execute or call the procedure
select #ident -- select or print the genereated id

Cannot insert the value NULL into column 'Id' although Id is set

I have a strange problem.
I want to insert an item to a table from database. I use Entity Framework.
Although the Id is set, I keep getting the following error:
Cannot insert the value NULL into column 'Id', table 'project_atp.dbo.ShoppingCarts'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."}
The table definition:
CREATE TABLE [dbo].[ShoppingCarts] (
[Id] INT NOT NULL,
[Guid] UNIQUEIDENTIFIER NULL,
[Name] NVARCHAR (255) NULL,
[Code] NVARCHAR (255) NULL,
[SupplierNo] NVARCHAR (255) NULL,
[SupplierName] NVARCHAR (255) NULL,
[Price] NVARCHAR (50) NULL,
[Quantity] INT NULL,
CONSTRAINT [PK_ShoppingCarts] PRIMARY KEY CLUSTERED ([Id] ASC)
);
Can you please advise what could be wrong here! Thanks!
By default Entity Framework assumes that an integer primary key is database generated. As the result Entity Framework would not include Primary Key field in the actual INSERT statement.
I would try to either play along and ALTER the table to auto-generate the ID (which judging by your comment you did)
or set StoreGeneratedPattern property of OnlineCarStore.Models.ShoppingCarts Id column to 'None'
or use annotation: [DatabaseGenerated(DatabaseGeneratedOption.None)].

SQL Trigger on Insert to call a Function and Manipulate Values

I am having a problem knowing set up a trigger on insert to call a function and passing an identifier SiteID to that function which then operates on variables from another table.
I have the table, where values are inserted:
CREATE TABLE [dbo].[Tests] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[SiteID] NVARCHAR (128) NOT NULL,
[Date] NVARCHAR (MAX) NULL,
[Time] NVARCHAR (MAX) NULL,
[Tub] NVARCHAR (MAX) NULL,
[FCl] FLOAT (53) NOT NULL
PRIMARY KEY CLUSTERED ([Id] ASC)
);
Every time a value is inserted in to the Tests table I would like a function to be called which uses the table Review to perform a simple calculation (see the trigger down the post below):
CREATE TABLE [dbo].[Review] (
[SiteID] NVARCHAR (128) NOT NULL,
[TubNum] INT NOT NULL,
[Supplied] INT NULL,
[Performed] INT NULL,
[Remaining] INT NULL
PRIMARY KEY CLUSTERED ([SiteID] ASC)
);
This is my sqlfiddle so far, however, I am unable to save it with the functions I am working on, which are here:
The trigger - not sure how to pass the SiteID for the insert or call the function:
CREATE TRIGGER [dbo].[TRIG_MyTable]
ON [dbo].[Tests]
AFTER INSERT
AS
CALL CalcRemaining() //how to pass it SiteID?
and the the function itself:
CREATE FUNCTION [dbo].[CalcRemaining](#ID NVARCHAR (128))
RETURNS NULL
AS
BEGIN
SELECT (Supplied, Performed FROM Review WHERE SiteID = ID);
Performed = Performed + 1;
INSERT INTO Review (Performed, Remaining) VALUES (Performed, (Supplied-Performed))
RETURN;
END
The idea is that the SiteID from the inserted line is passed to the function when called, the function then selects the values Supplied and Performed for that matching SiteID from the Review table. The Performed value is incremented by 1 and that new value along with the retrieved Supplied value are subtracted and written to the Remaining field in the Review table.
If the assumptions I've asked about in the comments are valid (that Remaining and Performed can always be calculated), here's how I'd implement your database structure, with no trigger nor function:
Base tables:
CREATE TABLE dbo.Tests (
[Id] INT IDENTITY (1, 1) NOT NULL,
[SiteID] NVARCHAR (128) NOT NULL,
[Date] NVARCHAR (MAX) NULL,
[Time] NVARCHAR (MAX) NULL,
[Tub] NVARCHAR (MAX) NULL,
[FCl] FLOAT (53) NOT NULL
PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE TABLE dbo._Review (
[SiteID] NVARCHAR (128) NOT NULL,
[TubNum] INT NOT NULL,
[Supplied] INT NULL,
PRIMARY KEY CLUSTERED ([SiteID] ASC)
);
Then a view that calculates Performed:
CREATE VIEW dbo._Tests_Count
WITH SCHEMABINDING
AS
SELECT
SiteID,
COUNT_BIG(*) as Performed
FROM
dbo.Tests t
GROUP BY SiteID
GO
CREATE UNIQUE CLUSTERED INDEX IX_Tests_Count ON dbo._Tests_Count (SiteID)
And finally a view that re-creates the original Review table:
CREATE VIEW dbo.Review
WITH SCHEMABINDING
AS
SELECT
r.SiteID,
r.TubNum,
r.Supplied,
COALESCE(tc.Performed,0) as Performed,
r.Supplied - COALESCE(tc.Performed,0) as Remaining
FROM
dbo._Review r
left join
dbo._Tests_Count tc WITH (NOEXPAND)
on
r.SiteID = tc.SiteID
GO
If needed, at this point a trigger could be created on this Review view to allow any INSERTs, DELETEs and UPDATEs to be performed against it rather than _Review, if you cannot change some calling code.
You have to be completely sure you're manipulating ONLY one row at a time!
CREATE TRIGGER [dbo].[TRIG_MyTable]
ON [dbo].[Tests]
AFTER INSERT
AS
DECLARE #SiteID NVARCHAR (128)
SELECT #SiteID = ID FROM inserted
CALL CalcRemaining(#SiteID)

an error occured while the batch was being executed

I'm trying to make a simple table in a database.
CREATE TABLE [dbo].[klanten]
(
[Klant_naam] TEXT NOT NULL PRIMARY KEY,
[Klant_adres] TEXT NULL,
[klant_gsm] TEXT NULL,
[klant_gewicht] INT NOT NULL,
[klant_lengte] INT NOT NULL,
[klant_klacht] TEXT NOT NULL
)
When I try to update it, the following error pops-up.
As the documentation warns:
ntext , text, and image data types will be removed in a future version
of Microsoft SQL Server. Avoid using these data types in new
development work, and plan to modify applications that currently use
them. Use nvarchar(max), varchar(max), and varbinary(max) instead.
So, try this instead:
CREATE TABLE [dbo].[klanten] (
[Klant_naam] varchar(max) NOT NULL PRIMARY KEY,
[Klant_adres] varchar(max) NULL,
[klant_gsm] varchar(max) NULL,
[klant_gewicht] INT NOT NULL,
[klant_lengte] INT NOT NULL,
[klant_klacht] varchar(max) NOT NULL
)
Well, this doesn't quite work either, because there is a limit of 900 bytes for index keys. How about using a surrogate key and reasonable column lengths?
CREATE TABLE [dbo].[klanten] (
Klant_Id int not null identity(1, 1) primary key,
[Klant_naam] varchar(255) NOT NULL unique,
[Klant_adres] varchar(max) NULL,
[klant_gsm] varchar(max) NULL,
[klant_gewicht] INT NOT NULL,
[klant_lengte] INT NOT NULL,
[klant_klacht] varchar(max) NOT NULL
);
Try to change "TEXT" data type to "NCHAR()" or any other similar to this.
This error usually occured when you try to update database, but some fields can't be updated. For example, I have 5 fields in a table:
[Id] INT IDENTITY (1, 1) NOT NULL,
[Path] NVARCHAR (MAX) NOT NULL,
[Name] NVARCHAR (50) NOT NULL,
[Url] NVARCHAR (MAX) NULL,
[SecureUrl] NVARCHAR (MAX) NULL
I've worked for some time with it, and make some records. And some of them have value NULL at [Url]. Suddenly I decide to change table:
[Id] INT IDENTITY (1, 1) NOT NULL,
[Path] NVARCHAR (MAX) NOT NULL,
[Name] NVARCHAR (50) NULL,
[Url] NVARCHAR (MAX) NOT NULL, //!!! HERE A PROBLEM, I ALREADY HAVE NULL RECORDS IN DATA
[SecureUrl] NVARCHAR (MAX) NULL
Problem is that my data has been made with the old model and it has records with the NULL at [Url], but in new model NULL value can't be at [Url]. So as with new model, old data can't be correct. Thus we have the error when update.

If the field was essentially changed, then change the value of one of its column

I have the essence of the "Requirements". If the user has changed the field "Description" in this instance, it should automatically change the value of the field "Stability" (dropdownlist). That is, if you had to change the description of the requirements, it becomes unstable. I wrote a trigger
CREATE TRIGGER [ChangeStabilityRequirement]
ON [dbo].[Requirement] AFTER UPDATE
AS
BEGIN
if update([Definition])
begin
update [Requirement] set Stability = 2
where RequirementId in (select RequirementId from inserted)
end
end
But the problem is that the trigger is activated when any change entries in the table. A need to respond only to changes in the column "Definition".
MY TABLE
CREATE TABLE [dbo].[Requirement] (
[RequirementId] INT IDENTITY (1, 1) NOT NULL,
[Rationale] NVARCHAR (MAX) NULL,
[CreatedOn] DATE CONSTRAINT [DF__Requireme__Creat__473C8FC7] DEFAULT (getdate()) NULL,
[CurentVersion] NVARCHAR (MAX) NULL,
[State] INT NOT NULL,
[Priority] INT NOT NULL,
[Type] INT NOT NULL,
[Source_BusinessRuleId] INT NULL,
[Stability] INT NOT NULL,
[UserPart] NVARCHAR (MAX) NULL,
[CreatedBy_UserId] INT NULL,
[Responsible_UserId] INT NULL,
[ImplementationVersion] NVARCHAR (MAX) NULL,
[ResponsibleId] INT DEFAULT ((0)) NULL,
[SourceId] INT DEFAULT ((0)) NULL,
[InterfacePoint_InterfacePointId] INT NULL,
[InterfacePointId] INT DEFAULT ((0)) NULL,
[CreatedById] INT DEFAULT ((0)) NULL,
[Definition] NVARCHAR (MAX) DEFAULT ('') NOT NULL,
CONSTRAINT [PK_dbo.Requirement] PRIMARY KEY CLUSTERED ([RequirementId] ASC),
CONSTRAINT [FK_dbo.Requirement_dbo.User_CreatedById] FOREIGN KEY ([CreatedById]) REFERENCES [dbo].[User] ([UserId]),
CONSTRAINT [FK_dbo.Requirement_dbo.User_ResponsibleId] FOREIGN KEY ([ResponsibleId]) REFERENCES [dbo].[User] ([UserId]),
CONSTRAINT [FK_dbo.Requirement_dbo.BusinessRule_SourceId] FOREIGN KEY ([SourceId]) REFERENCES [dbo].[BusinessRule] ([BusinessRuleId])
);
Update table
Updating occurs in a web application interface
This is query from SQL SERVER Profile
exec [dbo].[Requirement_Update]
#RequirementId=32,
#Definition=N'Реализовать возможность выбора значения "Без пени" в поле "Тип начисления пени". Диалоговое окно АР-12',
#Rationale=N'В соответствии с изменением бизнес-правила',
#CreatedOn='2014-12-18 00:00:00',
#CurentVersion=N'2.1',
#ImplementationVersion=N'2.2',
#State=0,
#Priority=1,
#Stability=1,
#Type=0
Ok, if you need update Requirement only when Definition is updated then change your trigger as:
CREATE TRIGGER [ChangeStabilityRequirement]
ON [dbo].[Requirement] AFTER UPDATE
AS
BEGIN
if update([Definition]) AND NOT update([Rationale]) AND NOT update([CurentVersion])
--AND NOT UPDATE(.....list here all possible columns that may be updated
begin
update [Requirement] set Stability = 2
where RequirementId in (select RequirementId from inserted)
end
end