How to convert a query to a a function - sql-server

I'm playing around with a query from a software partner that i did not create. I'm trying to use it as a function that i can insert into a table, since i'm no sql expert i'm having difficulties with the sintax.
Thanks to your suggestions i'm making progress, now i'm stuck on how to add an additional select to include some join tables, i have disabled that part converting it to a comment. This actually works without the final select but i need the final select, any ideas?
alter function Renetest
(
#companytest nvarchar(8),
#fiscalyeartest int
)
returns #PERIODBALANCE TABLE
(
[Company] NVARCHAR(8)
,[BookID] NVARCHAR(12)
,[BalanceAcct] NVARCHAR(200)
,[FiscalYear] INT
,[FiscalPeriod] INT
,[BalanceType] NVARCHAR(1)
,[SegValue1] NVARCHAR(50)
,[SegValue2] NVARCHAR(50)
,[FiscalYearSuffix] NVARCHAR(8)
,[FiscalCalendarID] NVARCHAR(12)
)
as
begin
Declare #company nvarchar(8);
Declare #fiscalyear INT;
DECLARE #FiscalPeriod INT;
Set #company = 'epic03'
set #Fiscalyear = '2013'
SET #FiscalPeriod=0;
DECLARE #MaxPeriod AS NVARCHAR(20);
SET #MaxPeriod=(
SELECT
MAX([Erp].[GLBookPer].[FiscalPeriod])
FROM
[Erp].[GLBookPer] WITH (NOLOCK)
WHERE
[Erp].[GLBookPer].[Company] IN (#company)
AND [Erp].[GLBookPer].[FiscalYear]=#FiscalYear
);
WHILE #FiscalPeriod<=(#MaxPeriod)
BEGIN
INSERT INTO #PERIODBALANCE
(
[Company]
,[BookID]
,[BalanceAcct]
,[FiscalYear]
,[FiscalPeriod]
,[BalanceType]
,[SegValue1]
,[SegValue2]
,[FiscalYearSuffix]
,[FiscalCalendarID]
)
SELECT
[Erp].[GLPeriodBal].[Company]
,[Erp].[GLPeriodBal].[BookID]
,[Erp].[GLPeriodBal].[BalanceAcct]
,[Erp].[GLPeriodBal].[FiscalYear]
,#FiscalPeriod AS [FiscalPeriod]
,[Erp].[GLPeriodBal].[BalanceType]
,[Erp].[GLPeriodBal].[SegValue1]
,[Erp].[GLPeriodBal].[SegValue2]
,[Erp].[GLPeriodBal].[FiscalYearSuffix]
,[Erp].[GLPeriodBal].[FiscalCalendarID]
FROM
[Erp].[GLPeriodBal] WITH (NOLOCK)
WHERE
[Erp].[GLPeriodBal].[Company] IN (#company)
AND [Erp].[GLPeriodBal].[FiscalYear]=#FiscalYear
AND [Erp].[GLPeriodBal].[FiscalPeriod]<=#FiscalPeriod
AND [Erp].[GLPeriodBal].[BalanceType] IN ('D','B')
SET #FiscalPeriod=#FiscalPeriod+1;
end;
/*
SELECT
LTRIM(RTRIM([PERIODBALANCE].[Company])) AS [Company]
,LTRIM(RTRIM([PERIODBALANCE].[BookID])) AS [BookID]
,LTRIM(RTRIM(REPLACE([PERIODBALANCE].[BalanceAcct],'|','-'))) AS [BalanceAcct]
,LTRIM(RTRIM(ISNULL(NULLIF([PERIODBALANCE].[BalanceType],''),'--'))) AS [BalanceType]
,LTRIM(RTRIM(ISNULL(NULLIF([PERIODBALANCE].[FiscalYearSuffix],''),'--'))) AS [FiscalYearSuffix]
,LTRIM(RTRIM(ISNULL(NULLIF([PERIODBALANCE].[FiscalCalendarID],''),'--'))) AS [FiscalCalendarID]
FROM
#PERIODBALANCE AS [PERIODBALANCE]*/
return
end
go

The function returns a table. Just select from the function with an INSERT statement.
INSERT INTO dbo.MyTable
SELECT Company, BookID
FROM Renetest();
This is strictly what you asked. But this could be converted into a stored procedure and avoid using a function all together.

Related

how to dynamically find and replace the function text

I have 800+ functions in my database. I would need to modify their source databases dynamically and create snapshots.
example of the function:
create function [schema1].[funTest1] (#param1 varchar(50))
returns table as
return
(
select * from [curr_database1].[schema1].[funTest1](#param1)
union
select * from [curr_database2].[schema1].[funTest1](#param1)
)
I want to change the script as:
create or alter function [schema1].[funTest1] (#param1 varchar(50))
returns table as return
(
select * from [new_database2].[schema1].[funTest1](#param1)
union
select * from [new_database3].[schema1].[funTest1](#param1)
)
basically, I got all the functions script using the sys.syscomments. I'm looking for an option to find and replace the database dynamically to create the snapshots.
How can I get it? Thank you!
Here is the sample code that I have developed for sharing. All the database in the functions starts with the same text(for ex. "curr"). Please share your thoughts. Thanks in advance!
create or alter proc test_proc as
begin
set nocount on
-- this piece of code has the new databases
if object_id('tempdb..#dbNames') is not null drop table #dbNames
create table #dbNames (dbName varchar(1000), id int)
insert into #dbNames(dbName, id) values ('new_database2', 1),('new_database3', 2)
insert into #dbNames(dbName, id) values ('new_database8', 3),('new_database9', 4)
-- this one has the sample functions
if object_id('tempdb..#dbFunctions') is not null drop table #dbFunctions
create table #dbFunctions (funText nvarchar(max))
insert into #dbFunctions (funText) values('create function [schema1].[funTest1] (#param1 varchar(50))
returns table as
return
(
select * from [curr_database1].[schema1].[funTest1](#param1)
union
select * from [curr_database2].[schema1].[funTest1](#param1)
)'),
('create function [schema2].[funTest2] (#param1 varchar(50), #param2 varchar(100))
returns table as
return
(
select * from [curr_database4].[schema2].[funTest2](#param1, #param2)
union
select * from [curr_database5].[schema2].[funTest2](#param1, #param2)
)')
-- declare variables and assign value for #frmStr variable (for testing purposes)
declare #str nvarchar(max)
declare #dbName varchar(100)
declare #frmStr varchar(100) = '[curr_database1]'
-- get the total count of the databases and the functions to iterate and replace the string
declare #dbCnt int = (select count(id) from #dbNames)
declare #fnCnt int = (select count(*) from #dbFunctions)
while #dbCnt > 0
begin
set #dbname = (select dbname from #dbnames where id = #dbcnt)
while #fnCnt > 0
begin
-- this is where I would need to replace the code
select #str = replace(funText, #frmStr, #dbName) from #dbFunctions
select #str
set #fnCnt = #fnCnt - 1
end
set #dbCnt = #dbCnt - 1
end
end
Your actual goal isn't clear, but to answer the question you asked, you can use REPLACE functions in the query to syscomments that you used to get the code in the first place:
REPLACE(
REPLACE([FunctionTextColumn],'curr_database1','new_database2')
,'curr_database2','new_database3'
)

SQL: All the suggested GetDate () methods are not working

I'm doing an assignment and I was stuck at this place for about couple of days.
Getdate () is not working for this procedure. I used all the suggested methods.
But again I have to use the update statement here. So aren't there any procedure code to make it without using an update statement here?
Update Engineer set Enter_date = getdate() where EmpNo = 'Emp001000'
You don't need #temp_date,change #enter_date to GetDate()
exec sp_Add_New_Engineer #EmpNo='Emp00100', #EngNo= 'E00070' ,
#Eng_Type ='Electrical Engineer', #FName ='Pramila', #LName='Thivagaran',
#DOB ='1994/04/02', #Eng_Address='53/2, Peradeniya Road, Kandy', #Enter_Date = getdate(), #ProNo = 'P6'
Further I recommend formatting your code ,plus don't prefix your sps with SP_ .Here are some issues you may see when you use SP_
Where did you use #Temp_Date. You declared and assigned a value to it but never used in your remaining code. Please refer this sp below. I used your variable instead of #Enter_Date.
ALTER PROCEDURE sp_Add_New_Engineer (
#EmpNo VARCHAR(20)
,#EngNo VARCHAR(12)
,#Eng_Type VARCHAR(50)
,#FName VARCHAR(50)
,#LName VARCHAR(50)
,#DOB VARCHAR(50)
,#Eng_Address VARCHAR(100)
,#Enter_Date DATETIME
,#ProNo VARCHAR(12)
)
AS
DECLARE #Temp_Date DATETIME
SET #Temp_Date = GETDATE()
BEGIN
IF (
(
SELECT count(*)
FROM Supervisor
WHERE EmpNo = #EmpNo
) = 0
)
AND (
(
SELECT count(*)
FROM Labor
WHERE EmpNo = #EmpNo
) = 0
)
BEGIN
INSERT INTO Engineer (
EmpNo
,EngNo
,Eng_Type
,FName
,LName
,DOB
,Eng_Address
,Enter_date
,ProNo
)
VALUES (
#EmpNo
,#EngNo
,#Eng_Type
,#FName
,#LName
,#DOB
,#Eng_Address
,#Temp_Date
,#ProNo
)
END
ELSE
PRINT 'Employee Number is already in use'
END

How to get value inside trigger

i'm running my application using one DB but during some specific table insertion i'm calling trigger where i need to get some value from some another DB.Previously i did this by hard coding the specific DB name inside the trigger. i got it correctly but now i need to remove the dependency of that DB name.so i need to find get that particular value in some another way. Can anyone help me to find the solution please...
Previous trigger.
CREATE TRIGGER [dbo].[xC2C_ADT_Upd] on [dbo].[dmAppt] For Insert,UPDATE
AS
BEGIN
If Not Exists (Select top 1* from inserted)
Return
declare #ADT_ID UniqueIdentifier
Declare #personuid int
declare #ApptID int
select #personuid = PID, #ApptID = IDAppt from inserted
set #ADT_ID = NewID()
declare #MSG_Type varchar(1)
declare #AddDate datetime
declare #LastUpdateDate datetime
declare #ServerID [varchar](50)
declare #ClientDB [varchar](max)
declare #ClientID [varchar](50)
set #ServerID = Convert(varchar(50),CONNECTIONPROPERTY('local_net_address'))
set #ClientDB = db_name()
select #ClientID = ClientID from dm_asarum_Client_Master..Clients //here only my database is hardcoded
where DBName_Current = #ClientDB
Now i did some changes,
set #ClientID = (select top 1 CAST(CONTEXT_INFO as varchar(50)) from sys.dm_exec_sessions where context_info!=0x order by last_request_end_time desc) --ClientID from dm_asarum_Client_Master..Clients
i have set the Context_info value in some SP like the following.,
alter PROCEDURE [dbo].[dm_ApptResRecurrReasonRelViewSel]
(
#IDLocation int,
#IDApptResource int,
#StartDate datetime,
#IDApptResRecurr int,
#ClientID varchar(50)
)
AS
SET NOCOUNT ON;
Declare #context_info1 varbinary(128);
SET
#context_info1 = CAST(#ClientID as varbinary(128));
SET
CONTEXT_INFO #context_info1;
Now the problem is,Using the SQL Profiler i noticed, i can able the get the clintID inside this SP correctly. but it is not saving this Context_info inside sys.dm_exec_sessions correctly. when i ran this manually in sql like,
exec [dm_ApptResRecurrReasonRelViewSel] #IDLocation=101,#IDApptResource=59,#StartDate='2016-05-27 17:00:00',#IDApptResRecurr=NULL,#ClientID='cl_obgyn_reg'
i context_info value is updated correctly i don't know where i missied.

Can't insert a second row into a table though it insert first row by stored procedure

It inserted a first row successfully but it's not inserting any other row, though second row has no conflict of primary key
Code in my aspx.cs file:
outputParVal = sqlCmd.Parameters[outputParName].Value;
outparameter in stored procedure is--- "Result"
CREATE PROCEDURE [dbo].[RecruiterProfileInsert]
#CompanyId int,
#CompanyName varchar(200),
#EmailId varchar(50) ,
#Password varchar(20) ,
#ContactNumber varchar(15),
#Website varchar(50),
#CompanyProfile varchar(2000),
#IsVerified bit,
#Result Tinyint OutPut
--#CreatedDate datetime ,
--UpdatedDate datetime
AS
BEGIN
-- Insert statements for procedure here
--check whether #CompanyName already exist or not if exist then return
IF EXISTS(SELECT Top 1 * FROM RecruiterProfile WHERE #CompanyId = LTRIM(RTRIM(#CompanyId)))
BEGIN
SET #Result = 0-- Already Exists
END
ELSE
BEGIN
INSERT INTO RecruiterProfile
(
CompanyId,
CompanyName,
EmailId ,
Password ,
ContactNumber,
Website ,
CompanyProfile ,
IsVerified,
CreatedDate
)
VALUES
(
#CompanyId,
#CompanyName,
#EmailId ,
#Password,
#ContactNumber,
#Website,
#CompanyProfile,
#IsVerified,
GetDate()
)
set #Result =1
return
END
END
This is the problem:
SELECT Top 1 * FROM RecruiterProfile WHERE #CompanyId = LTRIM(RTRIM(#CompanyId))
This inherently makes no sense. You're comparing the variable to itself. Take the # sign out of one of the CompanyId references. The RTrim is unnecessary in SQL Server, and the LTrim doesn't make sense either because the later insert doesn't also LTrim so something is going to go wrong eventually.
Furthermore, inside of an EXISTS clause, TOP makes no sense unless you are using ORDER BY and doing something with the final result. Just do SELECT * inside of EXISTS clauses.
One more thing: if there is high concurrency and users could possibly try to insert the same thing at the same time, your query could still fail on a duplicate key violation.

SQL Server stored procedure avoid cursor

I have the following SQL Server stored procedure :
BEGIN TRAN
CREATE TABLE #TempTable (
SampleOrderID int,
SampleOrderNo varchar(512),
ChallanNoAndChallanDate varchar(MAX)
)
CREATE NONCLUSTERED INDEX #IX_Temp2_1 ON #TempTable(SampleOrderID)
DECLARE
#SQL as varchar(MAX)
SET #SQL=' SELECT SampleOrderID, SampleOrderNo FROM SampleOrder WHERE SampleOrderID IN (37808,37805,37767,37571,37745,37772,37843,37394,37909,37905,37903) '
INSERT INTO #TempTable (SampleOrderID, SampleOrderNo)
EXEC (#SQL)
DECLARE
#SampleOrderID as int,
#ChallanNoAndChallanDate as varchar(max)
DECLARE Cur_AB1 CURSOR GLOBAL FORWARD_ONLY KEYSET FOR
SELECT SampleOrderID FROM #TempTable
OPEN Cur_AB1
FETCH NEXT FROM Cur_AB1 INTO #SampleOrderID
WHILE(##Fetch_Status <> -1)
BEGIN--2
SET #ChallanNoAndChallanDate=''
SELECT #ChallanNoAndChallanDate= COALESCE(#ChallanNoAndChallanDate+ ',', '') + CONVERT(VARCHAR(12),ChallanDate,106)+':'+ChallanNo FROM Challan WHERE OrderID =#SampleOrderID AND OrderType=2
UPDATE #TempTable SET ChallanNoAndChallanDate=#ChallanNoAndChallanDate WHERE SampleOrderID=#SampleOrderID
FETCH NEXT FROM Cur_AB1 INTO #SampleOrderID
END--2
CLOSE Cur_AB1
DEALLOCATE Cur_AB1
SELECT * FROM #TempTable
DROP TABLE #TempTable
COMMIT TRAN
Output :
SamID SamNo ChallanNoAndDaet
37394 37394 ,31 May 2012:151592
37571 37571 ,31 May 2012:151580
37745 37745 ,31 May 2012:151582
37767 37767 ,30 May 2012:151507,31 May 2012:151576
37772 37772 ,31 May 2012:151587
37805 37805 ,31 May 2012:151574
37808 37808 ,31 May 2012:151573
37843 37843 ,31 May 2012:151588
37903 37903 ,31 May 2012:151597
37905 37905 ,31 May 2012:151596
37909 37909 ,31 May 2012:151593
It works successfully for small volume of data but When i try to execute it on a Large volume (i.e. more then 500,000 record) my C# interface throws the time out exception.
Can anyone help me edit my stored procedure to avoid the cursor?
Thanks for response.
I use this to avoid cursor in everywhere I need
DECLARE #num_rows int
DECLARE #cnt int
DECLARE #selected int
DECLARE #table1 TABLE (Id int not null primary key identity(1,1), col1 int )
INSERT into #table1 (col1) SELECT col1 FROM table2
SET #num_rows=##ROWCOUNT
SET #cnt=0
WHILE #cnt<#num_rows
BEGIN
SET #cnt=#cnt+1
SELECT
#selected=col1
FROM #table1
WHERE Id=#cnt
--do your stuff here--
END
I usually use something like the following:
SELECT #SampleOrderID = MIN (SampleOrderID) FROM #TempTable
WHILE #SampleOrderID IS NOT NULL
BEGIN
SET #ChallanNoAndChallanDate=''
SELECT #ChallanNoAndChallanDate= COALESCE(#ChallanNoAndChallanDate+ ',', '') + CONVERT(VARCHAR(12),ChallanDate,106)+':'+ChallanNo FROM Challan WHERE OrderID =#SampleOrderID AND OrderType=2
UPDATE #TempTable SET ChallanNoAndChallanDate=#ChallanNoAndChallanDate WHERE SampleOrderID=#SampleOrderID
SELECT #SampleOrderID = MIN (SampleOrderID) FROM #TempTable WHERE SampleOrderID > #SampleOrderID
END
This code would replace the cursor stuff you have.

Resources