MSSQL nvarchar IF PROCEDURE exec with nvarchar input - sql-server

I want know how to release IF with update and how to exec procedure with nvarchar input.
There are table Dictionary with 2 values ('Orig','Translated')
I need procedure that adds or replace "Trasnslated' depending on input. There must be 2 inputs, no more and no less. For example
CREATE PROCEDURE Translate_Orig (#Orig nvarchar(32),#Translated nvarchar(32))
AS
BEGIN
UPDATE Dictionary
IF EXISTS (SELECT * FROM Dictionary WHERE Dictionary.Orig=#Orig)
SET Dictionary.Translated=#Translated
ELSE INSERT INTO Dictionary VALUES (#Orig, #Translated);
END
GO
SET #Orig = N'Orig'
SET #Translated = N'traslated'
EXEC Translate_Orig (#Orig,#Translated);

CREATE PROCEDURE Translate_Orig (#Orig nvarchar(32),#Translated nvarchar(32))
AS
BEGIN
IF EXISTS (SELECT * FROM Dictionary WHERE Dictionary.Orig=#Orig)
BEGIN
UPDATE Dictionary
SET Dictionary.Translated=#Translated
END
ELSE INSERT INTO Dictionary VALUES (#Orig, #Translated);
END
GO
SET #Orig = N'Orig'
SET #Translated = N'traslated'
EXEC Translate_Orig (#Orig,#Translated);

Make sure you are just running the CREATE PROCEDURE through GO as a statement.

There EXEC that works fine. No brackets.
And "SET Dictionary.Translated=#Translated WHERE Dictionary.Orig=#Orig"
CREATE PROCEDURE Translate_Orig (#Orig nvarchar(32),#Translated nvarchar(32))
AS
BEGIN
IF EXISTS (SELECT * FROM Dictionary WHERE Dictionary.Orig=#Orig)
BEGIN
UPDATE Dictionary
SET Dictionary.Translated=#Translated WHERE Dictionary.Orig=#Orig
END
ELSE INSERT INTO Dictionary VALUES (#Orig, #Translated);
END
GO
DECLARE #Orig nvarchar(32);
DECLARE #Translated nvarchar(32);
SET #Orig = N'Name'
SET #Translated = N'Name_Translated'
EXEC Translate_Orig #Orig,#Translated;

Related

SQL server execute SP from sql table and update

The table below stores sql insert statements and I run those from a sp. I need to also add an insert to the last_run_dt column. I put the code together via existing stackoverflow questions. I need help implementing this in my code, any feedback will be helpful.
How can I update my code to update the last_run_dt column?
Table:
audit_sql_id audit_sql last_run_dt
1 select * from <<need to add last run_dt value>>
2 select * from <<need to add last run_dt value>>
Code:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
alter proc [dbo].[sp_sqlAudit]
#packagename as varchar(255)
as
begin
set nocount on;
if #packagename='SQL_DM_AUDIT'
begin
declare #queries table (audit_sql_id int identity(1,1),sqlscript varchar(max))
declare #str_query varchar(max);
declare #startloop int
declare #endloop int
insert into #queries
select audit_sql
from dw.dbo.audit_sql with(nolock)
select #endloop = max(audit_sql_id), #startloop = min(audit_sql_id)
from #queries
while #startloop < = #endloop
begin
select #str_query = sqlscript
from #queries
where audit_sql_id = #startloop
exec (#str_query)
set #startloop = #startloop + 1
end
end
end
I would suggest a slight refactor something like the below. There's no need to bring the entire list of sql statements into TemDB, just iterate over it and get each statement in turn. I would also always add a #debug parameter to print the sql instead if executing.
create or alter procedure dbo.sqlAudit
#packagename as varchar(255)
as
set nocount on;
declare #str_query varchar(max), #Id int
declare #AuditID table (Id int)
if #packagename='SQL_DM_AUDIT'
begin
insert into #AuditID (Id) /* Get list of IDs */
select audit_sql_id
from dw.dbo.audit_sql
while exists(select * from #AuditID) /* Continue while there are IDs in the list */
begin
select top (1) #Id=Id from #AuditID /* Get an ID */
select #str_query=audit_sql /* Get the sql for the ID */
from dw.dbo.audit_sql
where audit_sql_id=#Id
delete from #AuditID where Id=#Id /* Remove this ID from the list */
begin try
exec (#str_query)
if ##Error=0
begin
update dw.dbo.audit_sql set last_run_dt=GetDate() /* Update date for ID if run successful */
where audit_sql_id=#Id
end
end try
begin catch
/*handle error*/
end catch
end
end
go

Insert trigger: set value from procedure ends with 3609 error

I have to check if a specific value of an insert is null. If it is null, I want to give it a value from a stored procedure. This procedure returns a number like a sequence, but because I have SQL Server 2008 I had to create it myself:
CREATE PROCEDURE dbo.Get_BAV_PERSONALARCHIV_SEQUENCE ( #value BIGINT OUTPUT)
AS
BEGIN TRANSACTION;
INSERT dbo.BAV_Personalarchiv_Sequence WITH (TABLOCKX) DEFAULT VALUES;
ROLLBACK TRANSACTION;
SELECT #value = SCOPE_IDENTITY();
GO
I want to use the created value in my Insert Trigger if 'SYSROWID' is null (if it is null, it should be the only record with it) :
ALTER TRIGGER [dbo].[NT_BAV_PERSONALARCHIV_MITARBEITER_INSERT]
ON [dbo].[NT_BAV_PERSONALARCHIV_MITARBEITER]
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON;
If (SELECT SYSROWID FROM INSERTED) IS NULL
Begin
DECLARE #value BIGINT;
EXECUTE dbo.Get_BAV_PERSONALARCHIV_SEQUENCE #value OUTPUT;
Update dbo.NT_BAV_PERSONALARCHIV_MITARBEITER
SET SYSROWID = #value
where SYSROWID IS NULL
End
END
But sadly it returns with an 3609 error and rolls back the transaction.
Testing only the Execute and Update works without a problem:
DECLARE #value BIGINT;
EXECUTE dbo.Get_BAV_PERSONALARCHIV_SEQUENCE #value OUTPUT;
Update dbo.NT_BAV_PERSONALARCHIV_MITARBEITER
SET SYSROWID = #value
where SYSROWID IS NULL
What am I missing? Thank you for your help!
Ok, I found out that the rollback in the procedure causes the trigger to end with the error. My workaround is to delete the values of the "sequence"-table before I create a new value:
ALTER PROCEDURE dbo.Get_BAV_PERSONALARCHIV_SEQUENCE ( #value BIGINT OUTPUT)
AS
delete from dbo.BAV_Personalarchiv_Sequence
INSERT dbo.BAV_Personalarchiv_Sequence WITH (TABLOCKX) DEFAULT VALUES;
SELECT #value = SCOPE_IDENTITY();
GO

Efficiently return a value from a stored procedure

I have query which returns single value (i.e) count. I'm exceuting it using the stored procedure in the following way and using execute reader with dataset to get single value
CREATE PROCEDURE GetCnt
#EmpNo char(4)
AS
BEGIN
SET NOCOUNT ON;
Declare #Cnt int
SELECT #Cnt = count(*)
FROM employees
WHERE EMPLNO = #EmpNo
AND test = 'p'
BEGIN
SELECT #Cnt
END
END
is this effcient way
or Do I need to use the execute.scalar() and return value directly from the query instead of assigning to #cnt
can any one advise me
All ExecuteScalar does is get the first field from the first record.
Can't you just SELECT the count directly?
BEGIN
SET NOCOUNT ON
SELECT Count(*) FROM employees WHERE EMPLNO = #EmpNo AND test='p'
END
You do not need to create the variable. You just need the following:
CREATE PROCEDURE GetCnt
#EmpNo char(4)
AS
BEGIN
SET NOCOUNT ON;
SELECT count(1)
FROM employees
WHERE EMPLNO = #EmpNo
AND test = 'p'
END
Since this is only one value being returned from the stored procedure, you will likely want to use ExecuteScalar()

Calling a stored proc that returns a recordset from within a stored proc

Working in SQL Server 2005, I have a stored procedure that inserts a record and returns the new ID via SELECT ##IDENTITY; as the last command.
I then want to call this from another stored proc, and get the value of the new ID.
But I can't work out how to get the value returned from the first procedure.
Example:
CREATE PROCEDURE spMyInsert(#Field1 VARCHAR(10)) AS
BEGIN
INSERT INTO tMyTable (Column1) VALUES (#Field1); // ID column implicitly set
SELECT ##IDENTITY ID;
END
CREATE PROCEDURE spMyMain AS
BEGIN
DECLARE #NewID INT;
EXEC spMyInsert 'TEST';
// How do I set #NewID to the value returned from spMyInsert?
END
There is another question that nearly answers my question, but not quite. This explains how to insert the results into another table, but all I want to do is store it in a local variable.
Looking at other similar questions, the general answer is to change to either set an OUTPUT variable or create a function to do it, but I can't do this in my case as other .NET data access stuff uses the same stored proc, and I don't want to have to duplicate all the work of the stored procs as functions as well.
I couple of things that I've tried but all fail are:
SET #NewID = (EXEC spMyInsert 'TEST');
SET #NewID = (SELECT ID FROM (EXEC spMyInsert 'TEST'));
Anybody know how to do this?
Thanks,
Ben
By the way you should probably check that ##identity is what you need as opposed to scope_identity.
If it is what you need then it will still be accessible in the calling stored procedure too.
CREATE PROCEDURE spMyMain
AS
BEGIN
DECLARE #NewID INT;
EXEC spMyInsert 'TEST';
SET #NewID = ##IDENTITY
SELECT #NewID AS '#NewID'
END
The more general solution that would need to be applied if you use scope_identity and don't want to use either output parameters or the procedure return code is
CREATE PROCEDURE spMyMain AS
BEGIN
DECLARE #NewID INT;
DECLARE #IdHolder TABLE
(
id INT
)
INSERT INTO #IdHolder
EXEC spMyInsert 'TEST';
IF ##ROWCOUNT<>1
RAISERROR('Blah',16,1)
SELECT #NewID = id FROM #IdHolder
END
First, don't use ##IDENTITY, use SCOPE_IDENTITY() instead (search this site or Google for the reason why). Then just return the value in an output parameter:
CREATE PROCEDURE spMyInsert(#Field1 VARCHAR(10), #NewID int output) AS
BEGIN
INSERT INTO tMyTable (Column1) VALUES (#Field1);
SET #NewID = scope_identity();
END
go
CREATE PROCEDURE spMyMain AS
BEGIN
DECLARE #NewID INT;
EXEC spMyInsert #Field1 = 'TEST', #NewID = #NewID OUTPUT;
END
go
The issue here is that the spMyInsert returns a Select. When you execute spMyMain it will return the Select from spMyInsert and then the select from spMyMain
I would suggest that you amend spMyInsert to utilise OUTPUT parameters
CREATE PROCEDURE spMyInsert(#Field1 VARCHAR(10), #NewId int output) AS
BEGIN
INSERT INTO tMyTable (Column1) VALUES (#Field1); // ID column implicitly set
SELECT #NewId = ##SCOPE_IDENTITY;
END
and then
CREATE PROCEDURE spMyMain AS
BEGIN
DECLARE #NewID INT;
Set #NewId = 0
EXEC spMyInsert 'TEST', #NewId output;
select #NewId
// How do I set #NewID to the value returned from spMyInsert?
END
Note that I have also changed ##Identity to ##scope_identity It is better to use ##Scope_Identity as that will return the new ID that applies to the current connection.
Try this:
Execute #NewID = spMyInsert 'TEST'
Edit: After reading his question more thoroughly and realizing he was dealing with a select rather than a return: Could you wrap that procedure in a function call and then call the function?
select #NewId = from fnMyInsert('TEST')
An output parameter is the way to go, but if you really can't change the inner SP then, as you say, you can have the inner SP return its results to a table and then get the value out of there.
eg.
declare #NewID int,
#Customer table(CustomerId int);
insert into #Customer
exec spMyInsert 'TEST';
select #NewID = CustomerId from #Customer;

How do I get identity from one sproc and pass it in to another sproc?

Hi all i'm looking for a way to pass in a generated id from a sproc to another sproc.
i.e.
#name varchar(12),
#descript varchar(55)
#test_date date,
#test_result varchar(1)
BEGIN
EXEC ts_create_item #name, #descript
END
if (#test_date is not null) or (isnull(#test_result_id,'')!='')
BEGIN
Exec ts_update_test_results #itemid(generated from the sproc before), #test_date, #test_result
End
Is there a way to do this in sql server?
Thanks
Use an output variable
so you would declare the previous proc like
Create proc SomeProc (#parm1 int, #parm2 int, #id int = null OUTPUT)
as
Begin
...do some insert
select #id = scope_identity()
End
And remember, OUTPUT has to be specified both when declaring and assigning the parameter
ie.
Exec someproc #parm1, #parm2, #id OUTPUT
Alternately you can use a local variable to hold the result
e.g.
create proc somesample(#in int)
as
Begin
select #in * 2
End
declare #var int
exec #var = somesample 1
print #var
2

Resources