Reputation: 2994
I am trying to get data from one table in DB-Server-1, and pass it to a stored procedure being executed on DB-SERVER-2 (that joins to this data from DB-Server-1).
So, I have 2 tables on different servers:
DB-Server-1: tblItem
item_id | item_qty
--------+----------
1231 | 2
1232 | 4
DB-Server-2: tblItemDetails
item_detail_id | item_id | item_data
---------------+---------+--------------
1 | 1231 | TEST_DATA_1
2 | 1232 | TEST_DATA_2
Now I want to get data from DB-Server-1 (basic select query)
SELECT item_id, item_qty
FROM tblItem
WHERE item_id IN (1231, 1232);
And pass it to a stored procedure spSetItemQuantityInItemDetails
:
CREATE PROCEDURE [dbo].[spUpdatePOCartons]
(@valueList VARCHAR(MAX))
.
.
-- Now trying to split string and create a temp table
-- This temp table will later be used in the SP to join with tblItemDetails to set item_qty
DECLARE @temp TABLE
(
item_id int,
item_qty int
);
DECLARE @pos1 INT
DECLARE @len1 INT
DECLARE @value1 varchar(8000)
DECLARE @pos2 INT
DECLARE @len2 INT
DECLARE @value2 varchar(8000)
SET @valueList = '1,4;2,5;3,14;';
set @pos1 = 0
set @len1 = 0
WHILE CHARINDEX(';', @valueList, @pos1+1)>0
BEGIN
set @len1 = CHARINDEX(';', @valueList, @pos1+1) - @pos1
set @value1 = SUBSTRING(@valueList, @pos1, @len1)
--SELECT @pos, @len, @value /*this is here for debugging*/
PRINT @value1;
-----------
set @pos2 = 0
set @len2 = 0
WHILE CHARINDEX(',', @value1, @pos2+1)>0
BEGIN
set @len2 = CHARINDEX(',', @value1, @pos2+1) - @pos2
set @value2 = SUBSTRING(@value1, @pos2, @len2)
--SELECT @pos, @len, @value /*this is here for debugging*/
PRINT @value2;
set @pos2 = CHARINDEX(',', @value1, @pos2+@len2) +1
END
------------
set @pos1 = CHARINDEX(';', @valueList, @pos1+@len1) +1
END
Issue
I am trying to understand if the above solution is closest to what would work (currently it is not splitting last value of string which does not end with ; or , )
OR is there some better approach?
Upvotes: 0
Views: 68
Reputation: 2994
Thanks a lot everyone. Your insights really helped get to the solution. I was able to get the expected behaviour via :
IF OBJECT_ID('tempdb..#tval') IS NOT NULL DROP TABLE #tval;
CREATE TABLE #tval (val1 INT, val2 INT);
declare @s varchar(1000)
set @s = '1,11;2,22'
;WITH cte AS (
select value
from string_split(@s, ';')
)
INSERT INTO #tval
SELECT
MAX(CASE WHEN ord=1 THEN v END),
MAX(CASE WHEN ord=2 THEN v END)
FROM cte
CROSS APPLY (SELECT value AS v, ROW_NUMBER() OVER(ORDER BY 1/0) AS ord
FROM STRING_SPLIT([value], ',')) s
GROUP BY value;
SELECT * from #tval
Upvotes: 0
Reputation: 5770
I think a better approach might be to pass a table variable directly to the stored procedure. In order to do so, you'd have to create a type that creates a structure for the input table. I recreated this scenario below. Let me know if you can work with this to achieve your goals.
--Create test tables
CREATE TABLE dbo.tblItem (item_id int, item_qty int);
CREATE TABLE dbo.tblItem2 (item_detail_id int, item_id int, item_details varchar(50));
GO
--Create the type that can be used as input
CREATE TYPE TableForInput as TABLE
(
Item_Id int,
Item_Qty int
);
GO
--Create/alter the stored procedure
CREATE PROCEDURE dbo.usp_GetCardData
@Input TableForInput READONLY
AS
BEGIN
SELECT * FROM dbo.tblItem2 as t2 INNER JOIN @Input as i ON t2.Item_id = i.Item_id
END
GO
--Insert dummy data into the test tables
INSERT INTO dbo.tblItem values (1231, 2), (1232, 4);
INSERT INTO dbo.tblItem2 VALUES (1, 1231, 'TEST_1'), (2, 1232, 'TEST2')
-- The below would mimic the client side.
-- Declare a local temporary table, select data into it
-- And then pass this as a parameter to the stored proc
DECLARE @Data TableForInput;
INSERT INTO @Data
SELECT * FROM dbo.tblItem;
exec dbo.usp_GetCardData @Data
Upvotes: 1