Is a recursively called stored procedure possible in SQL Server? - sql-server

Here is what I have as VBScript Subroutine:
sub buildChildAdminStringHierarchical(byval pAdminID, byref adminString)
set rsx = conn.execute ("select admin_id from administrator_owners where admin_id not in (" & adminString & ") and owner_id = " & pAdminID)
do while not rsx.eof
adminString = adminString & "," & rsx(0)
call buildChildAdminStringHierarchical(rsx(0),adminString)
rsx.movenext
loop
end sub
Is there anyway to turn this into a stored procedure since it's got the recursive call in the subroutine?
Here is what I've tried...
CREATE PROCEDURE usp_build_child_admin_string_hierarchically
#ID AS INT,
#ADMIN_STRING AS VARCHAR(8000),
#ID_STRING AS VARCHAR(8000) OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #index int;
DECLARE #length int;
DECLARE #admin_id int;
DECLARE #new_string varchar(8000);
SET #index = 1;
SET #length = 0;
SET #new_string = #ADMIN_STRING;
CREATE TABLE #Temp (ID int)
WHILE #index <= LEN(#new_string)
BEGIN
IF CHARINDEX(',', #new_string, #index) = 0
SELECT #length = (LEN(#new_string) + 1) - #index;
ELSE
SELECT #length = (CHARINDEX(',', #new_string, #index) - #index);
SELECT #admin_id = CONVERT(INT,SUBSTRING(#new_string, #index, #length));
SET #index = #index + #length + 1;
INSERT INTO #temp VALUES(#admin_id);
END
DECLARE TableCursor CURSOR FOR
SELECT Admin_ID FROM Administrator_Owners WHERE Admin_ID NOT IN (SELECT ID FROM #temp) AND Owner_ID = #ID;
OPEN TableCursor;
FETCH NEXT FROM TableCursor INTO #admin_id;
WHILE ##FETCH_STATUS = 0
BEGIN
IF LEN(#ID_STRING) > 0
SET #ID_STRING = #ID_STRING + ',' + CONVERT(VARCHAR, #admin_id);
ELSE
SET #ID_STRING = CONVERT(VARCHAR, #admin_id);
EXEC usp_build_child_admin_string_hierarchically #admin_id, #ID_STRING, #ID_STRING;
FETCH NEXT FROM TableCursor INTO #admin_id;
END
CLOSE TableCursor;
DEALLOCATE TableCursor;
DROP TABLE #temp;
END
GO
But I get the following error when that stored procedure is called...
A cursor with the same name 'TableCursor' already exists.

You can specify a LOCAL cursor, like this:
DECLARE TableCursor CURSOR LOCAL FOR
SELECT ...
At least in SQL Server 2008 R2 (my machine), this allows you to recursively call the sproc without running into "Cursor already exists" errors.

The problem is that while your cursor isn't global, it is a session cursor. Since you're doing recursion, even though each iteration is creating a cursor in a new proc scope, they're all being created in the same PID (connection) at the same time, thus the collision.
You'll need to generate unique cursor names in each iteration of the procedure based on some criteria that won't be reproduced during the recursion.
Or, preferably, find a way to do what you need using set logic, and handle any necessary recursion using a recursive CTE.

You can, but it's usually not a good idea. SQL is made for set-based operations. Also, in MS SQL Server at least, the recursion is limited to the number of recursive calls that it can make. You can only nest up to 32 levels deep.
The problem in your case is that the CURSOR lasts through each call, so you end up creating it more than once.

Related

How to return value 1 stored procedure

I have written a stored procedure for inserting name and email address:
CREATE PROCEDURE [dbo].[usp_Referral_Email]
#user_key varchar(36),
#name nvarchar(100),
#email nvarchar(500),
#result int output
AS
BEGIN
DECLARE #username Nvarchar(500)
DECLARE #useremail Nvarchar(500)
DECLARE #CusrsorID CURSOR
SET #CusrsorID = CURSOR FOR
SELECT Value,Value1
FROM ufn_split_string(#name,#email)
OPEN #CusrsorID
FETCH NEXT FROM #CusrsorID INTO #username, #useremail
WHILE ##FETCH_STATUS = 0
BEGIN
declare #user nvarchar(36)
begin try
begin transaction trans_Referral_Email
IF NOT EXISTS (SELECT 1 FROM dbo.C_User_Credentials
WHERE email = #useremail)
BEGIN
IF NOT EXISTS (SELECT 1 FROM dbo.Referral_Email
WHERE R_Email = #useremail)
BEGIN
INSERT INTO dbo.Referral_Email (CFK_C_UP_key, R_Name, R_Email)
VALUES (#user_key, #username, #useremail)
SET #result = 1
END
ELSE
BEGIN
SET #result = 0
END
END
ELSE
BEGIN
SET #result = 0
END
COMMIT transaction trans_Referral_Email
end try
begin catch
rollback transaction trans_Referral_Email
set #result=ERROR_MESSAGE()
end catch
FETCH NEXT FROM #CusrsorID INTO #username, #useremail
END
CLOSE #CusrsorID
DEALLOCATE #CusrsorID
END
As a example I will pass value
#name = ramesh,suresh,rahul
#email = ramesh#gmail.com,suresh#gmail.com,rahul#gmail.com
before inserting we checking condition email address are exists or not, suppose email address is exist it will not insert into the table.
Now my problem is i will explain through example. ramesh#gmail.com and suresh#gmail.com are new email address both email address are will insert into the table so return value is 1 rahul#gmail.com already exist in table so it will insert into the table so return value will be 0 and output #return value will be 0 but we have inserted 2 email address so i need #return value should be 1 as out put.
So my question is if at any place of email address is insert into the table if one email address also insert output should be #return=1
What you need is known as a "latch" (archaic) or as a flag variable, and is pretty common.
A flag variable (in this case, #result) should be initialized outside the loop and then set when a condition arises (in this case, a record is inserted). The variable should not be touched when any subsequent records are skipped. That way it acts as a sort of an OR gate.
Like this:
CREATE PROCEDURE [dbo].[usp_Referral_Email]
#user_key varchar(36),
#name nvarchar(100),
#email nvarchar(500),
#result int output
AS
BEGIN
DECLARE #username Nvarchar(500)
DECLARE #useremail Nvarchar(500)
DECLARE #CusrsorID CURSOR
SET #CusrsorID = CURSOR FOR
SELECT Value,Value1
FROM ufn_split_string(#name,#email)
OPEN #CusrsorID
FETCH NEXT FROM #CusrsorID INTO #username, #useremail
SET #result = 0 --<--- Will stay 0 until one or more rows are inserted
WHILE ##FETCH_STATUS = 0
BEGIN
declare #user nvarchar(36)
begin try
begin transaction trans_Referral_Email
IF NOT EXISTS (SELECT 1 FROM dbo.C_User_Credentials
WHERE email = #useremail)
BEGIN
IF NOT EXISTS (SELECT 1 FROM dbo.Referral_Email
WHERE R_Email = #useremail)
BEGIN
INSERT INTO dbo.Referral_Email (CFK_C_UP_key, R_Name, R_Email)
VALUES (#user_key, #username, #useremail)
SET #result = 1 --<--- Will stay 1 for the rest of its lifespan, even if other rows are not inserted
END
END
COMMIT transaction trans_Referral_Email
end try
begin catch
rollback transaction trans_Referral_Email
set #result=ERROR_MESSAGE()
end catch
FETCH NEXT FROM #CusrsorID INTO #username, #useremail
END
CLOSE #CusrsorID
DEALLOCATE #CusrsorID
END
Notice I've removed a bunch of the ELSE conditions, since you don't need to do anything when a record is skipped.
you are trying to process/insert several users with 1 stored procedure call and you can't use a single output INT field to return back insert status for several users.
Better to split #name and #email parameters at application level and pass to your (modified) stored procedure only a SINGLE pair of name and email. You will then have to call the spT from application level several times for each name/email pair.
If you still want to use a single spT for batch user insert, you will have to record each insert status into a temp table or table variable and then at the spT end you will have to SELECT from that temp table or table variable.
This way at application level you will have a row with status returned for each name/email input pair.
But I personally suggest you actually change your spT to be called once per each name/email pair. It's a better and cleaner approach.
HTH

how to use bulk collect in db2 cursor

Here is my procedure, I don't know how to use bulk collecton in cursor, that we can batch process the cursor data. Please help me, thanks!
CREATE PROCEDURE PROC_AUTOACTIVE
BEGIN ATOMIC
DECLARE v_sql VARCHAR(800);
DECLARE v_customer_id BIGINT;
DECLARE v_cardnum varchar(500);
DECLARE v_cardtype varchar(20);
DECLARE v_status varchar(10);
DECLARE v_lastname varchar(200);
DECLARE v_email varchar(150);
DECLARE v_mobile varchar(30);
DECLARE v_phone varchar(30);
DECLARE v_zipcode varchar(20);
DECLARE v_crm_mobile varchar(30);
DECLARE v_address varchar(500);
DECLARE v_order_count BIGINT;
DECLARE v_order_no varchar(500);
DECLARE not_found CONDITION FOR SQLSTATE '02000';
DECLARE at_end INT DEFAULT 0;
DECLARE c_customers CURSOR FOR s_cardsinfo;
DECLARE CONTINUE HANDLER FOR not_found SET at_end = 1;
SET v_sql = 'select t.customer_id, v.CUSTOMER_ID, v.CARD_TYPE, v.STATUS
from customer_tempcard t,
vip_fields v
where t.tempcard_num=v.CUSTOMER_ID
and t.status=1
and v.STATUS=1
and exists (select id
from orders o
where o.FK_CUSTOMER=t.CUSTOMER_ID
and o.FK_ORDER_STATUS in (3,4,6)) ';
PREPARE s_cardsinfo FROM v_sql;
OPEN c_customers;
--fetch card info
LOOP_CUSTOMER_INFO:
LOOP
FETCH c_customers INTO v_customer_id,v_cardnum,v_cardtype,v_status;
IF at_end <> 0 THEN
SET at_end = 0;
LEAVE LOOP_CUSTOMER_INFO;
END IF;
select c.LOGON_ID, o.DEV_CUSTOMER_NAME,
o.DEV_MOBILE, o.DEV_PHONE, o.DEV_ZIP, o.DEV_ADDRESS, o.ORDER_NO
into v_email, v_lastname,
v_mobile, v_phone, v_zipcode, v_address, v_order_no
from orders o,customer c
where o.FK_CUSTOMER=c.ID
and o.FK_CUSTOMER=v_customer_id
and o.FK_ORDER_STATUS in (3,4,6)
order by o.ID desc
fetch first 1 rows only;
IF v_mobile <> null THEN
SET v_crm_mobile = v_mobile;
ELSE
SET v_crm_mobile = v_phone;
END IF;
update customer_tempcard ct
set ct.STATUS='0',
ct.UPDATE_TIME=current_timestamp
where ct.CUSTOMER_ID=v_customer_id;
update card_store cs
set cs.STATUS='0',
cs.UPDATE_TIME=current_timestamp
where cs.CARD_NUM=v_cardnum;
update vip_fields v
set v.LAST_NAME=v_lastname,
v.EMAIL=v_email, v.MOBILE=v_crm_mobile,
v.CUSTOMER_UPDATE_TIME=current_timestamp,
v.UPDATE_TIME=current_timestamp,
v.OPERATION_TYPE='2',
v.CREATE_SOURCE='2',
v.STATUS='0',
v.ZIP_CODE=v_zipcode,
v.ADDRESS=v_address
where customer_id = v_cardnum;
update customer c
set c.VIP_CARD_NUMBER=v_cardnum,
c.VIP_CARD_NAME=v_lastname,
c.VIP_EMAIL=v_email,
c.VIP_CARD_TYPE=v_cardtype,
c.LEVEL=v_cardtype,
c.VIP_ZIP=v_zipcode,
c.VIP_MOBILE=v_crm_mobile,
c.VIP_ADDRESS=v_address,
c.FK_CUSTOMER_GRADE='1'
where c.id=v_customer_id;
insert into beactiveinfo
values (default,v_cardnum,v_order_no,current_timestamp);
END LOOP;
CLOSE c_customers;
END
BULK COLLECT is part of the Oracle compatibility feature in DB2, so, firstly, you cannot use it in the DB2 SQL PL native context, which you are using in your procedure. Secondly, you don't use BULK COLLECT in a cursor. You use SELECT ... BULK COLLECT INTO an_array_variable ... to populate a PL/SQL array. If you intend then to loop over that array, you won't get any performance benefit over the cursor, while incurring the memory overhead for storing the entire result set in the application memory.

How can I make this query more efficient by reducing index seeks?

I have a function which I want to be more efficient. I know that most of the cost is in seeking index. I want to know if there is a way to merge these two index seeks into one.
Here is my function
ALTER FUNCTION [dbo].[Search]
(
#Query nvarchar(150)
)
RETURNS #result TABLE
(
ID int,
ResultPhrase nvarchar(max),
Domain nvarchar(50)
)
AS
BEGIN
declare #id int,
#OffsetArticle nvarchar(50),
#OffsetProfile nvarchar(50),
#index int,
#domain nvarchar(50),
#StringResult nvarchar(max),
#substrIndex int,
#substrCount int,
#field nvarchar(40),
#begin int,
#end int
DECLARE pidCursor CURSOR FAST_FORWARD
FOR select id,OffsetArticle,OffsetProfile from PerfTest where contains (data,#Query)
open pidCursor
FETCH NEXT FROM pidCursor INTO #id,#OffsetArticle,#OffsetProfile
while (##FETCH_STATUS = 0)
begin
select #index = CHARINDEX(#Query,data) from PerfTest where ID=#id
exec #domain = dbo.FindDomain #id=#id ,#index=#index, #offsetArticle=#OffsetArticle, #offsetProfile=#OffsetProfile
if(#domain = N'Profile')
set #end = SUBSTRING(#offsetProfile,CHARINDEX(N'-',#offsetProfile)+1,len(#offsetProfile)-CHARINDEX(N'-',#offsetProfile))
set #begin = SUBSTRING(#offsetProfile,1,CHARINDEX(N'-',#offsetProfile)-1)
if(#domain = N'Article')
set #end = SUBSTRING(#OffsetArticle,CHARINDEX(N'-',#OffsetArticle)+1,len(#OffsetArticle)-CHARINDEX(N'-',#OffsetArticle))
set #begin = SUBSTRING(#OffsetArticle,1,CHARINDEX(N'-',#OffsetArticle)-1)
if(#index - 20 < CAST(#begin as int))
set #substrIndex = #index
else
set #substrIndex = #index - 20
if(#index + 150 > CAST(#end as int))
set #substrCount = #end
else
set #substrCount = #index + 150
select #StringResult = SUBSTRING(data,#substrIndex,#substrCount) from PerfTest where ID=#id
insert #result (id,ResultPhrase,Domain) values (#id,#StringResult,#domain)
if(##FETCH_STATUS = 0)
FETCH NEXT FROM pidCursor INTO #id,#OffsetArticle,#OffsetProfile
end
CLOSE pidCursor
DEALlOCATE pidCursor
RETURN
END
For combining the #index and #string result query, you could do the following:
DECLARE #results TABLE
(index INT, stringresult NVARCHAR(MAX))
INSERT INTO #results(Index,stringresult)
SELECT CHARINDEX(#Query,data)
,SUBSTRING(data,#substrIndex,#substrCount
FROM PerfTest where ID=#id
SET #index = (SELECT index from #results)
SET #stringresults = (SELECT stringresult FROM #results)
This will read the perftest table only once, then read the results from a in memory table into the two variables
Include
CHARINDEX(#Query,data)
in the cursor, instead of calculating it first thing inside the loop. That should cut of about half of the seeks. While seeks are the most efficient access way for SQL Server, eliminating half of them is still going to help any query.
You could also try to include data in the cursor and calculate #StringResult using that value. If that is going to help is very dependent on the avg size of the data column. If it is small enough that should speed things significantly. What "small enough" is is dependent on a lot of things and you should try it out. If data is VARCHAR(1000) pulling it in the cursor it is most likely going to help, however if it is VARCHAR(MAX) with and average length of 2 MB it is most likely going to hurt.
Finally, as Pete mentioned, the best solution would be to write this in a set-based fashion, but that might be more complex, as you can't call a stored procedure from inside a single select statement.

String Expression to be evaluated to number

I need to write a TSQL user defined function which will accept a string and return a number.
I will call the function like dbo.EvaluateExpression('10*4.5*0.5') should return the number 22.5
Can any one help me to write this function EvaluateExpression.
Currently I am using CLR function which I need to avoid.
Edit1
I know this can be done using stored procedure, but I want to call this function in some statements ex: select 10* dbo.EvaluateExpression('10*4.5*0.5')
Also I have around 400,000 formulas like this to be evaluated.
Edit2
I know we can do it using osql.exe inside function as explained here. But due to permission settings, I can not use this also.
I don't think that is possible in a user defined function.
You could do it in a stored procedure, like:
declare #calc varchar(max)
set #calc = '10*4.5*0.5'
declare #sql nvarchar(max)
declare #result float
set #sql = N'set #result = ' + #calc
exec sp_executesql #sql, N'#result float output', #result out
select #result
But dynamic SQL, like exec or sp_executesql, is not allowed in user defined functions.
Disclaimer: I'm the owner of the project Eval SQL.NET
For SQL 2012+, you can use Eval SQL.NET which can be run with SAFE Permission.
The performance is great (better than UDF) and honors operator precedence and parenthesis. In fact, almost all the C# language is supported.
You can also specify parameters to your formula.
-- SELECT 225.00
SELECT 10 * CAST(SQLNET::New('10*4.5*0.5').Eval() AS DECIMAL(18, 2))
-- SELECT 70
DECLARE #formula VARCHAR(50) = 'a+b*c'
SELECT 10 * SQLNET::New(#formula)
.Val('a', 1)
.Val('b', 2)
.Val('c', 3)
.EvalInt()
Use this Function, It will absolutely working.
CREATE FUNCTION dbo.EvaluateExpression(#list nvarchar(MAX))
RETURNS Decimal(10,2)
AS
BEGIN
Declare #Result Decimal(10,2)
set #Result=1
DECLARE #pos int,
#nextpos int,
#valuelen int
SELECT #pos = 0, #nextpos = 1
WHILE #nextpos > 0
BEGIN
SELECT #nextpos = charindex('*', #list, #pos + 1)
SELECT #valuelen = CASE WHEN #nextpos > 0
THEN #nextpos
ELSE len(#list) + 1
END - #pos - 1
Set #Result=#Result*convert(decimal(10,2),substring(#list, #pos + 1, #valuelen))
SELECT #pos = #nextpos
END
RETURN #Result
END
You Can use this
Select 10* dbo.EvaluateExpression('10*4.5*0.5')
You can use the SQL Stored procedure below to calculate the result of any formula with any number of variables:
I wrote in 2012 a solution which can evaluate any type of Mathematical formula using SQL SERVER. The solution can handle any formula with N variables :
I was asked to find a way to evaluate the value given by a Formula which is filled by the user.
The Formula contains mathematical operations (addition, multiplication, division and subtractions)
The parameters used to calculate the formula are stored in the SQL server DATA BASE.
The solution I found by myself was as follows:
Suppose I have n parameters used to calculate the formula, each of these parameters is stored in one row in one data table.
The data table containing the n rows to use in the formula is called tab_value
I have to store the n values found in n rows (in tab_values) in one single row in one new Table, using SQL cursor,
for that I create a new table called tab_formula
In the cursor, I will add a new column for each value, the column name will be Id1,Id2,Id3 etc.
Then I construct a SQL script containing the formula to evaluate the formula
Here after the complete script, I hope you find it useful, you are welcome to ask me about it.
The procedure uses as input:
-The formula
-A table containing the values used to calculate the formula
if exists(select 1 from sysobjects where name='usp_evaluate_formula' and xtype='p')
drop proc usp_evaluate_formula
go
create type type_tab as table(id int identity(1,1),val decimal(10,2))
go
create proc usp_evaluate_formula(#formula as nvarchar(100),#values as type_tab readonly)
as begin
declare #tab_values table (id int, val decimal(10,2))
insert into #tab_values(id,val) select * from #values
declare #id as int declare #val as decimal(10,2)
if not exists(select 1 from sysobjects where name ='tab_formula')
create table tab_formula(id int identity(1,1), formula nvarchar(1000))
if not exists(select 1 from tab_formula where formula=#formula)
insert into tab_formula(formula) values(#formula)
declare c cursor for select id,val from #tab_values
declare #script as nvarchar(4000)
open c
fetch c into #id,#val
while ##fetch_status=0
begin
set #script = 'if not exists(select 1 from syscolumns c inner join sysobjects o on c.id=o.id where o.name=''tab_formula'' and c.name=''id'+
convert(nvarchar(3),#id)+ ''')
alter table tab_formula add id'+convert(nvarchar(3),#id)+ ' decimal(10,2)'
print #script
exec(#script)
set #script='update tab_formula set id'+convert(nvarchar(3),#id)+'='+convert(nvarchar(10),#val)+' where formula='''+#formula+'''' print #script exec(#script) fetch c into #id,#val end close c deallocate c
set #script='select *,convert(decimal(10,2),'+#formula+') "Result" from tab_formula where formula='''+#formula+''''
print #script
exec(#script)
end
go
declare #mytab as type_tab
insert into #mytab(val) values(1.56),(1.5) ,(2.5) ,(32),(1.7) ,(3.3) ,(3.9)
exec usp_evaluate_formula'2*cos(id1)+cos(id2)+cos(id3)+3*cos(id4)+cos(id5)+cos(id6)+cos(id7)/2*cos(Id6)',#mytab
go
drop proc usp_evaluate_formula
drop type type_tab
drop table tab_formula

Splitting A String into Multiple Values in SQL Server 2000

I'm asking the question on behalf of someone that works for my client that asked me this. I'm actually more familiar with mySQL than SQL Server, but unfortunately, SQL Server is what the client has used for years.
The question basically this: Is there a way in SQL Server to split a string into multiple values (e.g. array?) that can be used in a WHERE statement.
Here's a PHP example of what I'm talking about.
<?php
$string = "10,11,12,13";
$explode = explode(",", $string);
?>
$explode would be equal to array(10,11,12,13). What I need to do is something like this:
SELECT {long field list] FROM {tables} WHERE hour IN SPLIT(",", "10,11,12,13")
With SPLIT being my pseudo-code function that performs the splitting
The reason why I'm not doing this in, let's say, PHP, is because the query is being constructed by reporting software where we can't perform logic (such as my PHP code) before sending it to the database, and the multiple values are being returned by the software as a single string separated by pipes (|).
Unfortunately I do not have access to the reporting software (I think he said it was called Logi or LogiReports or something) or the query my associate was drafting up, but all that is really important for this question is the WHERE clause.
Any ideas?
Dynamic SQL can be used:
declare #in varchar(10)
set #in = '10,11,12,13'
exec ('SELECT {long field list] FROM {tables} WHERE hour IN (' + #in + ')')
Several methods here: Arrays and list in SQL Server
For short strings, I prefer a numbers table
I could copy/paste from here but it really is worth reading
You could use a Function which receives a string containing the "id's" separated by pipes, and return it as a table, which you can query and use in a subquery maybe, like this:
SELECT {long field list] FROM {tables} WHERE hour IN
(SELECT OrderID from dbo.SplitOrderIDs('2001,2002'))
ALTER FUNCTION [dbo].[SplitOrderIDs]
(
#OrderList varchar(500)
)
RETURNS
#ParsedList table
(
OrderID int
)
AS
BEGIN
DECLARE #OrderID varchar(10), #Pos int
SET #OrderList = LTRIM(RTRIM(#OrderList))+ ','
SET #Pos = CHARINDEX(',', #OrderList, 1)
IF REPLACE(#OrderList, ',', '') <> ''
BEGIN
WHILE #Pos > 0
BEGIN
SET #OrderID = LTRIM(RTRIM(LEFT(#OrderList, #Pos - 1)))
IF #OrderID <> ''
BEGIN
INSERT INTO #ParsedList (OrderID)
VALUES (CAST(#OrderID AS int)) --Use Appropriate conversion
END
SET #OrderList = RIGHT(#OrderList, LEN(#OrderList) - #Pos)
SET #Pos = CHARINDEX(',', #OrderList, 1)
END
END
RETURN
END
you can use this stored procedure.
I hope that be useful for you.
CREATE PROCEDURE SP_STRING_SPLIT (#String varchar(8000),#Separator Char(10),#pos_select int=0)
AS
BEGIN
SET NOCOUNT ON
DECLARE #Caracter varchar(8000)
DECLARE #Pos int
Set #Pos=1
Set #Caracter=''
CREATE TABLE #ARRAY
( String varchar(8000) NOT NULL,
Pos int NOT NULL IDENTITY (1, 1)
)
While (#Pos<=len(#String))
Begin
If substring(#String,#Pos,1)=Ltrim(Rtrim(#Separator))
Begin
INSERT INTO #ARRAY SELECT #Caracter
SET #Caracter=''
End
Else
Begin
--forma la palabra}
Set #Caracter=#Caracter+substring(#String,#Pos,1)
End
If #Pos=len(#String)
Begin
INSERT INTO #ARRAY SELECT #Caracter
End
SET #Pos=#Pos+1
End
SELECT Pos,String FROM #ARRAY where (Pos=#pos_select Or #pos_select=0)
END
GO
exec SP_STRING_SPLIT 'HELLO, HOW ARE YOU?',',',0

Resources