webForumDet fria alternativet

loopa igenom en sträng i en Stored procedure

Databaser & SQL

4 svar · 901 visningar · startad av Vinnaren

Medlem sedan sep. 2005833 inlägg
Frågan#1

Hej alla!

Har följande:

ALTER PROCEDURE dbo.Page_UpdateOrder
	(
	@BlogId int,
	@OrderIdString varchar(max)
	)
AS
DECLARE @UnitPage int
DECLARE @idx int
DECLARE @tmp1 varchar(12)
DECLARE @tmp2 varchar(12)
DECLARE @ids varchar(max)
DECLARE @MyOrder int = 0
DECLARE @MenuId int
BEGIN TRY
BEGIN TRANSACTION

SET @UnitPage = (SELECT COUNT(*) FROM Menu WHERE BlogId = @BlogId)

UPDATE Menu SET [Order] = @UnitPage, Show = 0 WHERE BlogId = @BlogId

SELECT @idx = CHARINDEX(',', @OrderIdString)

WHILE (@idx > 0)
BEGIN

	SET @MyOrder = (@MyOrder + 1)

	SET @tmp1 = LEFT(@OrderIdString, @idx - 1)
	SET @ids = RIGHT(@OrderIdString, LEN(@OrderIdString) - @idx)
	SET @idx = CHARINDEX(',', @ids)

	SET @MenuId = CONVERT(INT, @tmp1)

	if not exists(SELECT 1 FROM Menu WHERE BlogId = @BlogId AND MenuId = @MenuId)
		INSERT INTO Menu(MenuId, BlogId, Show, [Order]) VALUES(@MenuId, @BlogId, 1, @MyOrder)
	else
		UPDATE Menu SET [Order] = @MyOrder, Show = 1 WHERE BlogId = @BlogId AND MenuId = @MenuId 

END

COMMIT TRANSACTION
END TRY

BEGIN CATCH
ROLLBACK TRANSACTION
DECLARE @ErrorMessage NVARCHAR(4000);
SELECT @ErrorMessage = ERROR_MESSAGE();
RAISERROR (@ErrorMessage, 16, 1);

END CATCH

Jag vill kunna skicka in en sträng(@OrderIdString) som kan se ut: 3,2,1,2 och då loopa genom dessa nummer. (Ska även gå att enbart skicka in en 3 utan något , efter)
Som det är nu får jag ut varje siffra med ett , efter. vilket gör att den krashar vid SET @MenuId = CONVERT(INT, @tmp1)

Hur löser man detta? :stud

Medlem sedan juni 20003 076 inlägg
#2

Till det använder man enklast en split funktion:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=50648

Medlem sedan sep. 2005833 inlägg
#3

Härligt, tack.

Tänkte köra på:

ALTER FUNCTION dbo.Split
(
	@RowData varchar(max),
	@SplitOn nvarchar(5)
)  
RETURNS @RtnValue table 
(
	Id int identity(1,1),
	Data nvarchar(100)
) 
AS  
BEGIN 
	Declare @Cnt int
	Set @Cnt = 1

	While (Charindex(@SplitOn,@RowData)>0)
	Begin
		Insert Into @RtnValue (data)
		Select 
			Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))

		Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
		Set @Cnt = @Cnt + 1
	End
	
	Insert Into @RtnValue (data)
	Select Data = ltrim(rtrim(@RowData))

	Return
END

Hur tar jag emot resultatet i den lagrade procedurern och loopar igenom raderna?

Medlem sedan juni 20003 076 inlägg
#4

Du joinar bara med tabellen du vill hämta info ur.
Ex:

select o.OrderID, o.OrderDate
from Orders o
inner join dbo.Split('1,2,3,4,5,6', ',') temp on o.OrderID = temp.Data

Sen skulle du nog göra om fältet Data i funktionen från nvarchar(100) till en int istället!

Medlem sedan sep. 2005833 inlägg
#5

ok, tach, men jag hade tänkt att antingen köra en insert alt. update om raden finns eller ej i databasen. Därför jag tänkte att man var tvungen att först loopa genom varje rad från det spliten returnerade och sen antingen köra en insert eller update.

Jag vill alltså inte hämta ut något från mina tabeller utan köra update/indert.

Måste väl gå?

263 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
132 ms — deklarationer (db)
0 ms — hämta statistik (cache)
125 ms — hämta tråd, inlägg och bilagor (db)
135 ms — ändringar (db)