update two tables with one Store Procedure in SQL server? - sql

I have problem when I tried to update two tables in one Store Procedure I get the SqlException could some one help me
The INSERT statement conflicted with the FOREIGN KEY constraint "FK".
The conflict occurred in database "", table "dbo.Users", column
'userID'. The statement has been terminated.
ALTER PROCEDURE [dbo].[CreateProject]
#ProjectID UNIQUEIDENTIFIER,
#UserID UNIQUEIDENTIFIER,
#ProjectName NVARCHAR(50),
#Description NTEXT,
#EstStartDate DATETIME,
#EstEndDate DATETIME,
#StatusID SMALLINT,
#Priority SMALLINT
AS
INSERT INTO DBO.Projects VALUES
(#ProjectID,#ProjectName,GETDATE(),#Description,#EstStartDate,#EstEndDate,#StatusID,#Priority)
INSERT INTO Users_projects VALUES
(#ProjectID,#UserID)

Problem is with the Foreign Key of UserID. You need to insert UserId into the Users table first. Few pointers: "createProc" procedure generally should create the ProjectId and return as an OUTPUT parameter. Also, you may want to use username as input parameter and let the proc look up the UserId.

Related

SQL Server: how to insert a record into related table during an update?

Let's say we have two tables, Incidents and IncidentTracking:
Incidents (Id INT PRIMARY KEY,
CreatedOn Datetime,
State VARCHAR(50))
IncidentTracking (Id INT PRIMARY KEY,
IncidentId INT FOREIGN KEY REFERENCES TO Incidents.Id,
TrackingDate Datetime,
NewState VARCHAR(50))
How do I insert a new record into IncidentTracking while updating some incidents?
For example, I want to change the State for all incidents that are more than 90 days old to "Outdated", and insert a tracking info record where IncidentId is the updated incident (SCOPE_IDENTITY() maybe?), TrackingDate is GETDATE() and NewState is also "Outdated".
Can it be done all in one statement or should I write a cursor?
I'd use OUTPUT clause.
As IncidentTracking has a foreign key, it is not possible to OUTPUT directly to it. You'll get an error message if you try:
The target table 'dbo.IncidentTracking' of the OUTPUT INTO clause
cannot be on either side of a (primary key, foreign key) relationship.
Found reference constraint 'FK_IncidentTracking_Incidents'.
So, we can use a temporary table or table variable.
Like this:
BEGIN TRANSACTION;
DECLARE #T TABLE (IncidentId int, TrackingDate datetime, NewState varchar(50));
UPDATE [dbo].[Incidents]
SET [State] = 'Outdated'
OUTPUT
inserted.Id AS [IncidentId],
GETDATE() AS [TrackingDate],
inserted.[State] AS [NewState]
INTO #T ([IncidentId], [TrackingDate], [NewState])
WHERE [CreatedOn] < DATEADD(day, -90, GETDATE())
;
INSERT INTO [dbo].[IncidentTracking] ([IncidentId], [TrackingDate], [NewState])
SELECT [IncidentId], [TrackingDate], [NewState]
FROM #T;
COMMIT TRANSACTION;
Write a stored procedure to perform your task. You can put that kind of logic in a stored procedure easily enough.
If you will allow access to the table(s) outside of the procedure and still want the same behavior, a trigger is likely what you want (not a fan of them myself). Make sure, when writing your trigger, you remember that it will run against a recordset not a single record.
You could have a trigger on the state field that inserts into IncidentTracking, then you just need the one update. Or the other way around (adding to IncidentTracking updates State)
But why even have the State in the Incidents table? Just have an IncidentState table where you add every state change, and the latest added one is the current state for the incident.
You'd also probably want to make the State field a StateId column instead of a text code. Connected to a State table containing all the states.

Autogenerate ID in stored procedure -SQL

I have this stored procedure in SQL Server which I use in visual net to generate values for some table.
CREATE PROCEDURE grabardatos
#codigocliente int,
#nombre varchar(50),
#apellido varchar(50),
#sexo char(1),
#direcion varchar(50),
#telefono varchar(50),
#tipo varchar(50)
AS
BEGIN
INSERT INTO CLIENTES(Numero,Nombre,Apellido,Sexo,Direcion,Telefono,Tipo)
VALUES ( #codigocliente,#nombre,#apellido,#sexo,#direcion,#telefono,#tipo)
END
The parameter #codigocliente is the id of the table which, according to this code, has to be entered manually in visual net. How Can the id be autogenerated in the sql code of the stored procecure instead of being entered manually in visual net?
If the clientes table has an identity key, it will be automatically generated by SQL as part of the INSERT. You can then use ##identity to retrieve it's value.
The add the key to the table, you need to create a column
ALTER TABLE Add IdKey INT IDENTITY(1,1)
Note that during the INSERT, you cannot provide a value for this column...

Finding what value was inserted into an auto-incrementing field

I have two tables:
Rooms:
ID (auto-incrementing primary key, int)
Topic (varchar(50))
MangerId (varchar(50))
Rooms_Users:
UserId (varchar(50))
RoomId (varchar(50))
both fields together are the primary key
I want to insert a room but I also must insert the manger to the table rooms_users.
Here is what I have so far:
ALTER PROCEDURE [dbo].[Creat_Room] #MangerId varchar(50) ,#Topic varchar(50)
AS
BEGIN
SET NOCOUNT
insert into Rooms(ManagerId,Topic) values(#MangerId,#Topic)
insert into Rooms_Users(UserId,RoomId) values(#MangerId,?????????????)
END
The ????????????? is the problem: I don't know what to put here i want to put the roomid i insert above.
You can use the output clause. Look at MSDN here: OUTPUT Clause (Transact-SQL)
Example:
declare #tbl table
(
NewID int
)
insert into Rooms(ManagerId,Topic)
output inserted.ID into #tbl
values(#MangerId,#Topic)
Then the table variable will contains the new id given to the row you inserted
Use the SCOPE_IDENTITY() function:
ALTER PROCEDURE [dbo].[Create_Room]
#ManagerId varchar(50),
#Topic varchar(50)
AS
BEGIN
DECLARE #NewRoomID INT
insert into Rooms(ManagerId, Topic) values(#MangerId, #Topic)
SELECT #NewRoomID = SCOPE_IDENTITY()
insert into Rooms_Users(UserId, RoomId) values(#ManagerId, #NewRoomID)
END
This function will return the last inserted IDENTITY value in this particular scope - the scope of your stored procedure.

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.

SQL INSERT stored procedure not working

Create Proc CrearNuevoAnuncio
#Titulo varchar(250),
#Precio int,
#Descripcion varchar(250),
#IDCategoria int,
#IDImagen int,
#Login varchar(200)
AS
INSERT INTO Anuncio VALUES(
#Titulo,
#Precio,
#Descripcion,
#IDCategoria,
#IDImagen,
#Login
)
The error is because the table anuncio has 1 more attribute: "idAnuncio". It's the primary key, and it's the indentity (autoincrement).
So, how can I handle this is the missing thing is an Identity. I don't want to pass that parameter from my front-end.
You need to specify the explicit list of columns in your insert statement:
INSERT INTO
Anuncio(Titulo, Precio, Descripcion, IDCategoria, IDImagen, Login)
VALUES
(#Titulo, #Precio, #Descripcion, #IDCategoria, #IDImagen, #Login)
Otherwise, SQL Server will try to insert values for ALL columns which fails here. It cannot insert a value into an IDENTITY column - that column will be set automatically by SQL Server upon inserting a new row, and is guaranteed to be unique.
Is the ID field of type "INT IDENTITY" ? In that case, you could access the value of the newly inserted ID like this:
DECLARE #NewID INT
SET #NewID = SCOPE_IDENTITY()
and possibly return it from the stored proc:
RETURN #NewID
Marc
You need to specify which value goes to which field.
INSERT INTO Anuncio (field1, field2, ...) VALUES (#Titulo, ...)