Creating Autoincrement on AlphaNumeric in Stored Procedure - sql

My Table:
CREATE TABLE USER_DATA
([ID] NVARCHAR(10),[NAME] NVARCHAR(50))
My Stored Procedure:
CREATE PROC SP_INSERT_USER
#NAME VARCHAR(50)
AS
BEGIN
DECLARE #ID NVARCHAR(50)
DECLARE #IDTEMP INT
SELECT #IDTEMP=MAX(CAST(RIGHT([ID],3) AS INT) ) FROM USER_DATA
SELECT #IDTEMP=CASE WHEN #IDTEMP IS NULL THEN 1 ELSE #IDTEMP+1 END
SELECT #ID='RP'+RIGHT(('000'+CAST(#IDTEMP AS VARCHAR(10))),3)
INSERT INTO USER_DATA VALUES (#ID,#NAME)
END
Input:
SP_INSERT_USER 'Ajit'
SP_INSERT_USER 'Amit'
Output:
ID NAME
---------- --------------------------------------------------
RP001 Ajit
RP002 Amit
This code is working fine. But the ID is fixed. It is limited to 3 digits like 001, 002, etc. If it get 1000th employee, it is not displaying properly. Is there any way to make it dynamical without fixing the length?

Try this one -
CREATE TABLE dbo.USER_DATA
(
PK INT IDENTITY(1,1) PRIMARY KEY
, ID AS 'PR' + RIGHT('00' + CAST(PK AS VARCHAR(5)), 5)
, NAME NVARCHAR(50)
)
GO
CREATE PROC dbo.SP_INSERT_USER
#NAME VARCHAR(50)
AS BEGIN
INSERT INTO dbo.USER_DATA
VALUES (#NAME)
END
GO
EXEC dbo.SP_INSERT_USER 'Ajit'
EXEC dbo.SP_INSERT_USER 'Amit'
SELECT ID, NAME
FROM dbo.USER_DATA

Related

Insert stored procedure result set into Temp table and query temp table

I have the following stored proc which is trying to:
Execute system stored procedure (sp_monitorconfig) and put the result set into a temp table.
SELECT FROM this temp table and add 2 custom columns (SOURCESERVER & CollectionTime)
This final result set will be ingested into Logstash via jdbc job.
I'm currently using SAP ASE 16 (sybase) and am getting an incorrect syntax error at keyword 'exec'. I'm not sure if I have to prefix the stored proc or what, but I'm currently stumped and any help is appreciated.
USE db
GO
CREATE PROCEDURE sp_active_con_ratio.sql AS
DECLARE #servername varchar(32) DECLARE #collecttime DATETIME DECLARE #procparam varchar(32)
select
#servername = ##servername
select
#collecttime = getdate()
select
#procparam = 'number of user connections' CREATE TABLE #TempUserConnections
(
TempName varchar(35),
FreeConnections int,
ActiveConnections int,
PercentActive char(6),
MaxUsed int,
Reuse_cnt int,
Instance_Name varchar(30) NULL
)
INSERT INTO
#TempUserConnections (TempName, FreeConnections, ActiveConnections, PercentActive, MaxUsed, Reuse_cnt, Instance_Name)
exec sp_monitorconfig #procparam **ERROR HERE**
SELECT
#servername AS 'SOURCESERVER',
FreeConnections,
ActiveConnections,
PercentActive,
MaxUsed,
#collecttime AS 'CollectionTime'
FROM
#TempUserConnections
DROP TABLE #TempUserConnections
RETURN
GO
Thanks!
I'd forgotten that sp_monitorconfig has an optional input parameter (#result_tbl_name) that allows the operator to designate a table into which the results should be inserted.
From the documentation on sp_monitorconfig, Example #8 ...
First create the table to hold the results; while the table name can vary you'll want to keep the column names/datatypes as defined:
create table sample_table
(Name varchar(35),
Config_val int,
System_val int,
Total_val int,
Num_free int,
Num_active int,
Pct_act char(6),
Max_Used int,
Reuse_cnt int,
Date varchar(30),
Instance_Name varchar(35))
To capture a few metrics:
exec sp_monitorconfig "locks", sample_table
exec sp_monitorconfig "number of alarms", sample_table
Display metrics:
-- select * from sample_table
exec sp_autoformat sample_data
go
sp_autoformat sample_table
2> go
Name Config_val System_val Total_val Num_free Num_active Pct_act Max_Used Reuse_cnt Date Instance_Name
---------------- ---------- ---------- --------- -------- ---------- ------- -------- --------- ------------------- -------------
number of locks 10000 942 10000 9717 283 2.83 308 0 Aug 16 2020 12:26PM
number of alarms 400 0 400 386 14 3.50 14 0 Aug 16 2020 12:26PM
You could do something like this;
USE db
GO
CREATE PROCEDURE usp_active_con_ratio.sql AS
BEGIN
DECLARE #servername varchar(32) = (select ##servername)
DECLARE #collecttime DATETIME = (select getdate())
DECLARE #procparam varchar(32) = (select 'number of user connections')
CREATE TABLE #TempUserConnections
(
TempName varchar(35),
FreeConnections int,
ActiveConnections int,
PercentActive char(6),
MaxUsed int,
Reuse_cnt int,
Instance_Name varchar(30) NULL
)
INSERT INTO #TempUserConnections
(
TempName,
FreeConnections,
ActiveConnections,
PercentActive,
MaxUsed,
Reuse_cnt,
Instance_Name
)
-- Add the semi-colon to terminate the statement
EXEC sp_monitorconfig #procparam;
SELECT
#servername AS 'SOURCESERVER',
FreeConnections,
ActiveConnections,
PercentActive,
MaxUsed,
#collecttime AS 'CollectionTime'
FROM
#TempUserConnections
DROP TABLE #TempUserConnections
END
GO
As #larnu mentioned you should not use the prefix sp, a better prefix in my opinion is usp_.
Ensure the stored procedure you're calling (sp_monitorconfig) has a RETURN

How to recompile a user defined function in SQL Server when a dependency is updated?

I have a table valued function A that calls table valued functions B and C. Functions B and C are being updated (altered) as part of a migration however table A is not being updated as a result of this. How can I rebuild A without altering it?
Example (rollback is just added for convenience) SQL Fiddle:
BEGIN TRANSACTION
SET NOCOUNT ON;
CREATE TABLE DOGS
(
Id UNIQUEIDENTIFIER PRIMARY KEY,
Name NVARCHAR(255) NOT NULL,
Age INT NOT NULL,
)
INSERT INTO DOGS VALUES (NEWID(), 'Rocky', 12);
INSERT INTO DOGS VALUES (NEWID(), 'Sammy', 2);
INSERT INTO DOGS VALUES (NEWID(), 'Porthos', 5);
CREATE TABLE CATS
(
Id UNIQUEIDENTIFIER PRIMARY KEY,
Name NVARCHAR(255) NOT NULL,
Age INT NOT NULL,
)
INSERT INTO CATS VALUES (NEWID(), 'Mr. T', 15);
INSERT INTO CATS VALUES (NEWID(), 'Old Timer', 37);
INSERT INTO CATS VALUES (NEWID(), 'Mittens', 1);
SET NOCOUNT OFF;
GO
CREATE FUNCTION [GetCatsYoungerThan]
(
#age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name FROM CATS WHERE Age < #age
);
GO
CREATE FUNCTION [GetDogsYoungerThan]
(
#age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name FROM DOGS WHERE Age < #age
);
GO
CREATE FUNCTION [GetAnimalsYoungerThan]
(
#age INT
)
RETURNS TABLE AS
RETURN (
SELECT * FROM [GetCatsYoungerThan](#age)
UNION
SELECT * FROM [GetDogsYoungerThan](#age)
);
GO
ALTER FUNCTION [dbo].[GetDogsYoungerThan]
(
#age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name, Age FROM DOGS WHERE Age < #age
);
GO
ALTER FUNCTION [dbo].[GetCatsYoungerThan]
(
#age INT
)
RETURNS TABLE AS
RETURN (
SELECT Name, Age FROM CATS WHERE Age < #age
);
GO
EXEC sp_recompile '[GetAnimalsYoungerThan]';
--results
SELECT * FROM [GetAnimalsYoungerThan](15);
--Shows expected results
SELECT * FROM [GetCatsYoungerThan](15)
UNION
SELECT * FROM [GetDogsYoungerThan](15)
ROLLBACK TRANSACTION
Result:
Name
-------
Mittens
Porthos
Rocky
Sammy
Expected Result:
Name Age
-----------
Mittens 1
Porthos 5
Rocky 12
Sammy 2
My expectation is that sp_recompile would cause the function to be recompiled; however, that is either not happening or that is not good enough to update the values return by A.
My original plan was to recompile all the objects in the database using the following code but that requires sp_recompile to work.
DECLARE #ObjectName NVARCHAR(MAX);
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT [ROUTINE_SCHEMA] + '.' + [ROUTINE_NAME] AS [NAME]
FROM information_schema.routines
WHERE [ROUTINE_SCHEMA] = 'my_domain';
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO #ObjectName
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT 'Recompiling ' + #ObjectName + '...';
EXEC sp_recompile #ObjectName;
FETCH NEXT FROM MY_CURSOR INTO #ObjectName;
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
Thank you in advanced for your help.
This is a result of using SELECT * and the result of that performing early schema binding of your TVF.
You can get the desired result by running:
sp_refreshsqlmodule <tvf-name>
Which effectively re-binds the schema to the TVF, without the verbosity of an ALTER x...
But in the long run, try and avoid using SELECT *.

Return inserted row from stored procedure

I have the following stored procedure
CREATE PROCEDURE [dbo].[spInsert]
#name nvarchar(128),
AS
insert into NameIdentifier
( Name, Identifier)
values
( #name, NEWID());
SELECT #new_identity = SCOPE_IDENTITY()
SELECT * FROM NameAge where Id = #new_identity
Is there are a more efficient way to return the last inserted record complete with id and associated data?
Use Insertedwithin output clause,
As the follwoing:
CREATE PROCEDURE [dbo].[spInsert]
#name nvarchar(128),
AS
DECLARE #MyTableVar table(
Name varchar(50),
Identifier uniqueidentifier
;
insert into NameIdentifier
( Name, Identifier)
values
( #name, NEWID());
OUTPUT INSERTED.Name, INSERTED.Identifier
INTO #MyTableVar
SELECt Name,Identifier from #MyTableVar
Refreance:
Best way to get identity of inserted row?
SCOPE_IDENTITY() is used to get the last generated Identity value in an identity column in your scope , For GUID values either you get the guid before you insert it like I have done in the code below , or you use OUTPUT clause to get the guid generated by the Insert statement.
CREATE PROCEDURE [dbo].[spInsert]
#name nvarchar(128)
AS
BEGIN
SET NOCOUNT ON;
Declare #NewID UNIQUEIDENTIFIER = NEWID();
insert into NameIdentifier ( Name, Identifier)
values( #name, #NewID);
SELECT * FROM NameAge where Id = #NewID;
END
This should give you your desired functionality.
CREATE PROCEDURE [dbo].[spInsert]
#name nvarchar(128),
#Ret int Output
AS
BEGIN
insert into NameIdentifier
( Name, Identifier)
values
( #name, NEWID());
END
SET #Ret = ##IDENTITY
EDIT: This will return the id of your newly inserted row.
You can achieve this by using the output clause of SQL Server, you can read more about this here
if exists (select 1 from sys.tables where name = 'NameIdentifier ')
drop table NameIdentifier
create table NameIdentifier
(
id BIGINT IDENTITY(1,1)
,Name VARCHAR(100)
,Identifier uniqueidentifier
)
DECLARE #id TABLE
(
ID BIGINT
)
INSERT INTO NameIdentifier (Name,Identifier)
OUTPUT INSERTED.id INTO #id
VALUES('abcd',NEWID())
SELECT * FROM NameIdentifier N, #id I where N.id = I.id

How can I insert the results of a stored procedure into a new table

ALTER procedure [dbo].[staffscorecard]
#STAFF_ID INT = NULL
as
select
count(STAFF_ID) as countexel
from
TbStudentSurvey
where
FEEDBACK = 'excellent'
and STAFF_ID = ISNULL(#STAFF_ID, STAFF_ID)
select
Score as scoreexel
from
TbStaffScoreMaster
where
Status = 'Excellent'
exec [dbo].[staffscorecard]
GO
CREATE TABLE #temp ( countexel int, scoreexel int)
GO
INSERT INTO #temp (countexel , scoreexel)
EXEC [dbo].[staffscorecard]
GO
SELECT *
FROM #temp
GO
For a given staffid to calculate countexel and scoreexel you can re-write your stored procedure as:
create table TbStudentSurvey (STAFF_ID int,FEEDBACK varchar(20));
insert into TbStudentSurvey values (1,'excellent'),(1,'excellent'),(2,'excellent');
create table TbStaffScoreMaster (Score int,[Status] varchar(20));
insert into TbStaffScoreMaster values(100,'Excellent');
Go
create procedure [dbo].[staffscorecard]
#STAFF_ID INT = NULL,
#countexel int output,-- Explicitly declare output variables to fetch these values
#scoreexel int output
as
Begin
select
#countexel = count(STAFF_ID)
from
TbStudentSurvey
where
FEEDBACK = 'excellent'
and STAFF_ID = ISNULL(#STAFF_ID, STAFF_ID)
select
#scoreexel = Score
from
TbStaffScoreMaster
where
Status = 'Excellent'
End
GO
and then instead of using a temp table use a table variable because when you use temp tables,the table has to match the exact column layout as of the stored procedure.
--CREATE TABLE #temp (countexel int, scoreexel int)
--GO
--Create a table variable:
declare #temp table (countexel int, scoreexel int)
declare #countexel int, #scoreexel int,#STAFF_ID int;
--set value of staff Id for which you want to get countexel and scoreexel.
set #STAFF_ID = 1;
EXEC [dbo].[staffscorecard] #STAFF_ID ,#countexel output,#scoreexel output
INSERT #temp values (#countexel ,#scoreexel);
SELECT *
FROM #temp
GO
Method 2:
You can also write as:
alter procedure [dbo].[staffscorecard]
#STAFF_ID INT = NULL
as
Begin
select
count(STAFF_ID) as countexel , Score as scoreexel
from
TbStudentSurvey TSS
inner join TbStaffScoreMaster TSM on TSM.Status = TSS.FEEDBACK
where
FEEDBACK = 'excellent'
and STAFF_ID = ISNULL(#STAFF_ID, STAFF_ID)
group by STAFF_ID,Score
End
GO
declare #temp table (countexel int, scoreexel int)
declare #STAFF_ID int;
set #STAFF_ID = 1;--set value of staff Id for which you want to get countexel and scoreexel.
INSERT #temp EXEC [dbo].[staffscorecard] #STAFF_ID
SELECT *
FROM #temp
GO
Hope this helps!!

Passing multiple parameters into a Table valued function

I have a table valued function as below. When I am trying to pass more than one parameter at the same time I am getting a error like "Function has too many arguments specified" .
CREATE FUNCTION [dbo].[GetCompanyUsers](#CompanyId BIGINT)
RETURNS #Users TABLE (Id BIGINT,Contact NVarchar(4000))
AS
BEGIN
INSERT INTO #Users(Id,Contact)
SELECT [Id]
,ISNULL([FirstName],'')+' ' +ISNULL([LastName],'') AS [Contact]
FROM [dbo].[CompanyAddressesContacts]
WHERE [CompanyId]=#CompanyId
ORDER BY ISNULL([FirstName],'')+' ' +ISNULL([LastName],'')
RETURN
END
What modifications I require in the above code so that it allows multiple values and I need to use the function in a "WHERE" condition in my dataset.
WHERE(Document_RFIs.CreatedBy IN
(SELECT Id FROM dbo.GetCompanyUsers(#CompanyId)))
This may help (but the fundamental problem is - passing a comma delimited string is something to be avoided unless absolutely necessary - which explains why you have received so few answers):-
--set nocount on
--create table #Document_RFIs (
-- CreatedBy varchar(50),
-- columna varchar(50),
-- columnb varchar(50),
-- columnc varchar(50)
--)
--insert into #Document_RFIs values
-- ('albert einstein','another','value',null),
-- ('marie curie','some',null,'tuna'),
-- ('isaac newton','why','not','provide'),
-- ('kepler','some','test','data'),
-- ('robert boyle','with','your','question'),
-- ('john dalton','it',null,'would'),
-- ('enrico fermi','make','helping','you'),
-- ('peter higgs','so','much','easier')
--create table #CompanyAddressesContacts (
-- companyid int,
-- firstname varchar(50),
-- lastname varchar(50)
--)
--insert into #CompanyAddressesContacts values (22,'albert','einstein')
--insert into #CompanyAddressesContacts values (23,'marie','curie')
--insert into #CompanyAddressesContacts values (23,'isaac','newton')
--insert into #CompanyAddressesContacts values (24,null,'kepler')
--insert into #CompanyAddressesContacts values (25,'robert','boyle')
--insert into #CompanyAddressesContacts values (25,'enrico','fermi')
--insert into #CompanyAddressesContacts values (26,'peter','higgs')
declare #ids varchar(1024)
set #ids='23,24,25'
create table #id (
companyid int
)
declare #pos int
while DATALENGTH(#ids)>0 begin
set #pos=charindex(',',#ids)
if #pos>0 begin
insert into #id values (left(#ids,#pos-1))
set #ids=SUBSTRING(#ids,#pos+1,DATALENGTH(#ids))
end else begin
insert into #id values (#ids)
set #ids=''
end
end
select d.*
from #Document_RFIs d
where exists(
select cac.*
from #CompanyAddressesContacts cac
join #id i on i.companyid=cac.companyid
where isnull(cac.firstname+' ','')+isnull(cac.lastname,'')=d.CreatedBy
)
--drop table #id
--drop table #Document_RFIs
--drop table #CompanyAddressesContacts
I would do something like this:
First convert your #CompanyId to rows
WITH CompanyIds AS (
SELECT Id
FROM CompanyTable -- Same as the source of the #CompanyId
WHERE Id IN (#CompanyId)
)
Then extract all users
,Users AS (
SELECT UserId
FROM CompanyIds
CROSS APPLY (
SELECT Id AS UserId
FROM dbo.GetCompanyUsers(CompanyIds.Id)
) AS CA1
)
And then use it in the where statement
WHERE Document_RFIs.CreatedBy IN (SELECT UserId
FROM Users)