I have a master table "Repairs" and a detail table "RepairDetails" I am trying to write a procedure to update both tables when I send the appropriate parameters from my application. Here is my SQL:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[UpdateRepair]
#RepairID bigint,
#TypeID bigint = NULL,
#Directions nvarchar(3000) = NULL,
#NewDetails NewDetails READONLY
AS
BEGIN
SET NOCOUNT ON;
UPDATE Repairs
SET
TypeID = ISNULL(#TypeID, TypeID),
Directions = ISNULL(#Directions, Directions),
LastUpdate = SYSDATETIME()
WHERE RepairID = #RepairID;
IF #NewDetails IS NOT NULL UpdateRepairDetails;
END
where "NewDetails" is a User-defined table type and "UpdateRepairDetails" is a different stored procedure that takes #RepairID and #NewDetails as parameters.
I have an error and a question. The error message is:
Must declare the scalar variable "#NewDetails"
which I don't understand because it is defined.
And my question is: will the parameters "#RepairID" and "#NewDetails" get automatically passed to the "UpdateRepairDetails" procedure. If not, what is the proper approach to accomplish this?
You cannot assign NULL to a table variable. Hence you can't check whether a table variable is NULL.
Second: no. You should call as follows:
EXEC UpdateRepairDetails #RepairID, #NewDetails;
Related
I've got a stored procedure that is coded similarly to the following:
USE [database]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROC [dbo].[procedure_name]
#record_id int
, #record_value VARCHAR(MAX)
AS
BEGIN
UPDATE dbo.table_1
SET table_1_record_value = #record_value
WHERE table_1_record_int = #record_int
END
BEGIN
INSERT INTO table_2 COLUMNS (table_2_record_id, table_2_record_value) VALUES (#record_id, #record_value)
END
And I'm getting a syntax error. I've never had to write a stored procedure for an application that would accomplish both an UPDATE and an INSERT statement together.
The answer was provided by bbaird in the comments. Removing the BEGIN/END keywords fixed the problem. Thank you!
bbaird's full comment below:
If the procedure isn't created yet, you will need to do CREATE PROCEDURE. 2. The update and insert statements are independent, no need to put them in their own BEGIN...END block unless there is a conditional. 3. COLUMNS in the insert statement might also be throwing things off - it is not necessary so remove it.
The answers of Jake and bbard are correct.
Below the code of your stored procedure:
USE [database]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE OR ALTER PROC [dbo].[procedure_name]
#record_id int
, #record_value VARCHAR(MAX)
AS
BEGIN
UPDATE dbo.table_1
SET table_1_record_value = #record_value
WHERE table_1_record_int = #record_int
INSERT INTO table_2 COLUMNS (table_2_record_id, table_2_record_value)
VALUES (#record_id, #record_value)
END
For documentation of BEGIN and END look here
I have a transaction that calls a stored procedure which creates a temp table. I need to be able to access this temp table outside of the stored procedure after it has been ran. Note: for what I am trying to do, I cannot use global temp tables.
Example:
Here is an example of the stored procedure:
CREATE PROCEDURE [dbo].[GetChangeID]()
AS
BEGIN
IF OBJECT_ID('tempdb..#CurrentChangeID') IS NOT NULL
DROP TABLE #CurrentChangeID
SELECT '00000000-0000-0000-0000-000000000000' AS ChangeID INTO #CurrentChangeID
END
GO
Here is an example of the transaction:
BEGIN TRANSACTION
DECLARE #changeID uniqueidentifier
EXEC dbo.GetChangeID
DECLARE #test uniqueidentifier
SET #test = (SELECT ChangeID FROM #CurrentChangeID)
COMMIT TRANSACTION
GO
The issue is that it cannot find a table named #CurrentChangeID.
How can I make it to where it can see this table without declaring it as a global temp table such as ##CurrentChangeID?
------UPDATE------
So let me give more context to my question because that was just a simplified example. So what I am ultimately trying to do is this: 1. Begin Transaction 2. Call stored procedure that generates the GUID 3. Then update row in a given view that has a trigger. 4. Within that trigger get the GUID that was generated within the sp. 5. Commit.
First of all you can't get access to local temp table defined in SP outside stored procedure. It will always be out of scope.
Second you probalbly don't even need temp table. In your example:
SET #test = (SELECT ChangeID FROM #CurrentChangeID)
it looks like you want only one value.
I propose to use output parameter.
CREATE PROCEDURE [dbo].[GetChangeID](
#test UNIQUEIDENTIFIER OUTPUT
)
AS
BEGIN
-- ...
SET #test = '00000000-0000-0000-0000-000000000000';
END;
And call:
DECLARE #changeID uniqueidentifier
EXEC dbo.GetChangeID #chaneId OUTPUT;
SELECT #changeId;
Thank you lad2025 and Dan Guzman for your input. The way I was originally trying to do this was definitely incorrect.
I did, however, figure out a way to accomplish this task.
Modified Stored Procedure:
CREATE PROCEDURE [dbo].[GetChangeID]()
AS
BEGIN
DECLARE #ChangeID uniqueidentifier
...
Code that generates the uniqueidentifier, #ChangeID.
...
--This can be seen within the context of this batch.
SET CONTEXT_INFO #ChangeID
END
GO
Then anywhere within this transaction that you would like to access the changeID, you just have to use the following query:
SELECT CONTEXT_INFO as changeID
FROM sys.dm_exec_requests
WHERE session_id = ##SPID AND request_id = CURRENT_REQUEST_ID()
I am creating first time stored procedure but I don't know why this showing error. I also have many other post but didn't understand if someone can tell what I am doing wrong here.
Stored procedure:
SET ANSI_NULLS ON
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[DeleteOrganization]
#ORG_ID bigint
AS
BEGIN
SET NOCOUNT ON;
delete from Organizations where ORG_ID=#ORGID
delete from Institutes where INS_FK_ORGID=#ORGID
delete from Branches where BRN_ID=#ORGID
END
The variable is declared as #ORG_ID bigint with an underscore but you refer to it without the underscore: #ORGID. Pick one and use it consistently.
This should work:
ALTER PROCEDURE [dbo].[DeleteOrganization]
#ORGID bigint
AS
BEGIN
SET NOCOUNT ON;
DELETE FROM Organizations WHERE ORG_ID = #ORGID
DELETE FROM Institutes WHERE INS_FK_ORGID = #ORGID
DELETE FROM Branches WHERE BRN_ID = #ORGID
END
I'm making this stored procedure call:
exec sp_executesql N'EXEC MyStoredProcedure
#MyId = #0, #MyVarField = #1',
N'#0 int, #1 nvarchar(4000)',
#0=2, #1='lll/kkk'
The stored procedure is just a simple select, looking for MyVarField = 'lll/kkk', but the / in the parameter seems to break it... it can't find the db row anyway.
If I pass in 'ffflll' then it finds the row which contains lllkkk, just doesn't find it when there's a / in it. What's that about?
ALTER PROCEDURE [dbo].[MyStoredProcedure]
#MyId int,
#MyVarField varchar
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM MyTable WHERE VarField = #VarField
END
What do I need to do to the stored procedure to make it accept the / as part of a varchar?
Try making your parameter match the same type as the statement (and presumably the underlying column), and giving it a length:
ALTER PROCEDURE [dbo].[MyStoredProcedure]
#MyId int,
#MyVarField NVARCHAR(4000)
AS
...
I don't think the failure currently has anything to do with the slash. Try this:
CREATE PROCEDURE dbo.foo
#bar VARCHAR
AS
PRINT #bar;
GO
EXEC dbo.foo '12345';
For some background, please read:
Bad habits to kick : declaring VARCHAR without (length)
Forward slash (“/” ) is the shortcut for RUN command (like “go” in mysql or sqlserver).
http://power2build.wordpress.com/2011/12/09/forward-slash-in-sqlplus/
I have an SP like so (using SQL Server):
ALTER PROCEDURE [dbo].[sp_ClientNotes_update]
#id uniqueidentifier,
#ordering smallint = NULL,
#title nvarchar(20) = NULL,
#content text = NULL
AS
BEGIN
SET NOCOUNT ON;
UPDATE tbl_ClientNotes
SET ordering=#ordering, title=#title, content=#content
WHERE id=#id
END
I would like to only set the values if they are passed into the SP, i.e. not NULL. Can this be done?
This question seems to suggest the only way is using completely separate queries with conditionals, but for 3 optional parameters this would obviously be a nightmare!
Try this.
ALTER PROCEDURE [dbo].[sp_ClientNotes_update]
#id uniqueidentifier,
#ordering smallint = NULL,
#title nvarchar(20) = NULL,
#content text = NULL
AS
BEGIN
SET NOCOUNT ON;
UPDATE tbl_ClientNotes
SET ordering=ISNULL(#ordering,ordering),
title=ISNULL(#title,title),
content=ISNULL(#content, content)
WHERE id=#id
END
It might also be worth adding an extra part to the WHERE clause, if you use transactional replication then it will send another update to the subscriber if all are NULL, to prevent this.
WHERE id=#id AND (#ordering IS NOT NULL OR
#title IS NOT NULL OR
#content IS NOT NULL)
UPDATE tbl_ClientNotes
SET
ordering=ISNULL#ordering,ordering),
title=isnull(#title,title),
content=isnull(#content,content)
WHERE id=#id
I think I remember seeing before that if you are updating to the same value SQL Server will actually recognize this and won't do an unnecessary write.
One Idea:
UPDATE tbl_ClientNotes
SET ordering=ISNULL(#ordering, ordering),
title=ISNULL(#title, title),
content=ISNULL(#content, content)
WHERE id=#id
UPDATE tbl_ClientNotes
SET ordering=#ordering, title=#title, content=#content
WHERE id=#id
AND #ordering IS NOT NULL
AND #title IS NOT NULL
AND #content IS NOT NULL
Or if you meant you only want to update individual columns you would use the post above mine. I read it as do not update if any values are null
ALTER PROCEDURE LN
(
#Firstname nvarchar(200)
)
AS
BEGIN
UPDATE tbl_Students1
SET Firstname=#Firstname
WHERE Studentid=3
END
exec LN 'Thanvi'