2017-03-29 29 views
0

我有一個表#data,它有列IdCount。另外我有接受一個參數@id等於Id),並返回一個數據集(計數等於Count)存儲過程MyProc使用存儲過程的結果數據集計數更新列

我的目標是將Count列從IdMyProc不帶遊標。

我知道,這樣的事情不工作:

UPDATE d 
SET Count = (SELECT COUNT(*) FROM (EXEC MyProc d.Id)) 
FROM #data AS d 

是否有語法我不知道,或者是光標實現這一目標的唯一選擇?

PS:這是我的代碼質量和性能問題。調用存儲過程將是最簡單的方法,不需要重複50行SQL,但光標放慢了速度。

+0

遊標是唯一的方法。如果你想提高性能,你需要打開存儲過程,並嘗試以基於集合的方式重寫它,然後你可以爲一堆ID進行重寫。您也可以將您的SP重寫爲標量值函數。那麼你可以在沒有光標的情況下做到這一點,但你仍然會遇到性能問題。如果你發佈你的SP代碼,我們可能會進一步幫助 –

回答

1

我相信你可以使用下面的查詢:

IF OBJECT_ID('dbo.data') IS NOT NULL DROP TABLE data; 
    IF OBJECT_ID('dbo.MyFunct') IS NOT NULL DROP FUNCTION dbo.MyFunct; 
    GO 

    CREATE TABLE data 
    (
     ID  int, 
     [Count] int 
    ); 

    INSERT data VALUES (1,5), (1,10), (2,3), (4,6); 
    GO 

    UPDATE d 
    SET d.[Count] = f.CNT 
    FROM 
     (SELECT ID,COUNT(id) AS CNT FROM data GROUP BY ID) f 
    INNER JOIN data d ON f.ID = d.ID 

我不能找到一種方法,使用存儲過程。需要你可以使用表值功能:

CREATE FUNCTION dbo.MyFunct(@id INT) 
    RETURNS @i TABLE 
    (ID INT , CNT INT) 
    AS 
    BEGIN 
     INSERT INTO @i 
     SELECT ID,COUNT(id) AS CNT FROM data GROUP BY ID 
    RETURN 
    END; 
    GO 

    UPDATE d 
    SET d.[Count] = f.CNT 
    FROM dbo.MyFunct(1) f INNER JOIN data d ON f.ID = d.ID 
+0

使用幫助器*表值函數返回表的解決方案。謝謝! – Koopakiller

0

我不完全理解你在做什麼,但我認爲你的解決方案將涉及@@ ROWCOUNT;注意:

-- Sample data and proc... 
---------------------------------------------------------------------- 
IF OBJECT_ID('tempdb..#data') IS NOT NULL DROP TABLE #data; 
IF OBJECT_ID('dbo.MyProc') IS NOT NULL DROP PROC dbo.MyProc; 
GO 

CREATE TABLE #data 
(
    id  int, 
    [Count] int 
); 

INSERT #data VALUES (1,5), (1,10), (2,3), (4,6); 
GO 

CREATE PROC dbo.MyProc(@id int) 
AS 
BEGIN 
    SELECT 'some value' 
    FROM #data 
    WHERE @id = id; 
END; 
GO 

數據之前:

id   Count 
----------- ----------- 
1   5 
1   10 
2   3 
4   6 

使用例行@@ ROWCOUNT

DECLARE @someid int = 1; -- the value you're passing to your proc 

EXEC dbo.MyProc 1; 
DECLARE @rows int = @@ROWCOUNT; -- this is what you need. 

UPDATE #data 
SET [Count] = @rows 
WHERE id = @someid; 

數據後

id   Count 
----------- ----------- 
1   2 
1   2 
2   3 
4   6 
+0

'@@ ROWCOUNT'是一個有趣的想法,但不是我所需要的。核心問題是,我必須更新所有行。這意味着我必須經常打電話給我的SP,而光標會減慢速度。我想避免光標,但到目前爲止它看起來不可能 – Koopakiller

1

要做你說的,你需要一個功能,而不是一個過程。

CREATE FUNCTION dbo.myFunc (@Id INT) 
    RETURNS INT 
AS 
BEGIN 

    UPDATE someTable 
    SET someCol = 'someValue' 
    WHERE id = @Id; 

    RETURN @@ROWCOUNT; 
END 
GO 

然後在更新語句中調用函數;

UPDATE d 
    SET d.Count = dbo.myFunc(d.Id) 
    FROM #data AS d; 

但是,基於行的操作是不好的做法。你應該總是努力執行基於集合的操作,但是因爲我不知道你的過程是什麼,所以我不能提供比你想要做什麼更大的猜測(根本不使用過程):

DECLARE @data TABLE (Id INT); 

UPDATE x 
    SET x.someCol = 'SomeVal' 
OUTPUT INSERTED.id INTO @data 
    FROM someTable AS x 
INNER JOIN #data AS d 
     ON d.Id = x.Id; 

WITH cte (Id, myCount) AS (
    SELECT d.Id 
      ,COUNT(d.Id) AS myCount 
     FROM @data AS d 
    GROUP BY d.Id 
) 
UPDATE d 
    SET d.[Count] = c.myCount 
    FROM #data AS d 
INNER JOIN cte AS c 
     ON c.Id = d.Id; 
相關問題