chciałbym wykonać procedurę przechowywaną w ciągu każdego wiersza w zestawie bez używania kursor z mniej więcej tak:
SELECT EXEC dbo.Sproc @Param1 = Table1.id
FROM Table1
Używam T-SQL w SQL Server 2005. Myślę, że może to być możliwe przy użyciu funkcji, ale chciałbym użyć procedury przechowywanej, jeśli to możliwe (standardy firmy)Czy można wykonać procedurę składowaną na zestawie bez użycia kursora?
Odpowiedz
9 na 10 razy można zrobić, co chcesz, bez kursora lub pętli while. Jednakże, jeśli musisz użyć jednego, odkryłem, że podczas gdy pętle wydają się być szybsze.
Także, jeśli nie chcesz, aby usunąć lub zaktualizować tabelę, można użyć coś takiego:
DECLARE @id [type]
SELECT @id = MIN([id]) FROM [table]
WHILE @id IS NOT NULL
BEGIN
EXEC [sproc] @id
SELECT @id = MIN([id]) FROM [table] WHERE [id] > @id
END
Tak. Jeśli masz kolumnę można użyć w tabeli, aby oznaczyć te przetwarzane, można użyć PODCZAS istnieje:
DECLARE @Id int
WHILE EXISTS(SELECT * FROM Table1 WHERE Processed='N')
BEGIN
SELECT Top 1 @Id = id from Table1 WHERE Procesed='N'
EXEC dbo.Sproc @Id
UPDATE Table1 SET Processed = 'Y' WHERE Id = @Id
END
Alternatywnie, zrzucić identyfikatory do zmiennej temp tabeli lub tabel i usunąć po zakończeniu:
DECLARE @HoldTable table (Id int PRIMARY KEY)
DECLARE @Id int
INSERT INTO @HoldTable SELECT Id FROM Table1
WHILE EXISTS(SELECT * FROM @HoldTable)
BEGIN
SELECT @Id = id from @HoldTable
EXEC dbo.Sproc @Id
DELETE FROM @HoldTable where Id = @Id
END
Edytował swoją drugą odpowiedź. Wybrałeś @Id zamiast @HoldTable i miałeś klauzulę where 'where processed = 'N'', ale @HoldTable nie ma takiej kolumny. Druga opcja powinna teraz działać. Mam nadzieję, że dobrze zrozumiałem twoją intencję. – kralco626
Szczerze mówiąc, gdybym musiał wykonać przechowywanej proc do zestawu danych zamiast jeśli jeden rekord został napisany, napisałem kod oparty na zestawie zamiast używać zapisanego proc. Jest to jedyny skuteczny sposób, aby to zrobić, jeśli zamierzasz działać przeciwko dużemu zestawowi danych. Możesz przejść od godziny, aby wstawić wstawkę, którą przechowywany proc robi do sekund lub nawet milisekund. Nie używaj przetwarzania opartego na rekordach zawsze, gdy musisz przetworzyć zestaw danych, zwłaszcza z niemądrych powodów, takich jak ponowne użycie kodu. Wydajność przyspiesza ponowne użycie kodu.
Jest kilka rzeczy, w których absolutnie * musisz * używać kursorów, ale tak jak w przypadku GOTO, prawdziwa potrzeba jest naprawdę mała. Zgadzam się, że lepiej jest przeprowadzić przetwarzanie oparte na zestawach, gdziekolwiek to ma sens, ale twoje "mocne atuty ponownie wykorzystują kod" jest nieco ekstremistyczne. –
Ponieważ mówimy o differnce między minutami a milisekundami lub godzinami i sekundami (lub minutami), nie sądzę, że jest to ekstremizm. Programiści, którzy nie biorą pod uwagę wydajności bazy danych w porównaniu z ponownym użyciem kodu (szczególnie jeśli chodzi o używanie kursorów), generalnie mają bardzo źle działające bazy danych. – HLGEM
Jesteś tym, który powiedział, że to sekundy w stosunku do godzin. W tej sprawie ze Słomianem, kto mógłby się spierać? Ale jeśli różnica wynosi milisekundy w porównaniu z sekundami lub milisekundami w porównaniu z dwukrotnie większą liczbą milisekund, to zależy. – stannius
Jeśli to możliwe, napisałbym drugą wersję przechowywanego procesu, który odczytuje z tabeli tymczasowej.
Jeśli to nie jest możliwe, prawdopodobnie nie masz szczęścia.
Jeśli używasz programu SQL Server 2005 lub nowszego, nie przejmuj się kompatybilnością wsteczną i możesz przekonwertować swój kod na funkcję zdefiniowaną przez użytkownika (zamiast przechowywanego procesu), możesz użyć nowego " CROSS APPLY "operator, który używa składni bardzo podobnej do tego, co chcesz. Znalazłem here krótki wstęp (oczywiście, można również przeczytać Bols i MSDN)
Zakładając swój SP zwraca pojedynczą wartość o nazwie out_int Twój Przykładem mogą być zapisane jako:
SELECT T.id, UDF.out_int
FROM
Table1 T
CROSS APPLY
dbo.fn_My_UDF(T.id) AS UDF
This pobierze każdy "identyfikator" z Tabeli 1 i użyje go do wywołania fn_My_UDF, którego wynik pojawi się w ostatecznym zestawie wyników oprócz oryginalnego parametru.
Odmiana "CROSS APPLY" to "ZEWNĘTRZNE ZASTOSOWANIE". Są one odpowiednikami "INNER JOIN" i "LEFT JOIN", ale pracują nad dołączeniem do tabeli i UDF (i wywoływania drugiego w tym samym czasie).
Jeśli musisz musi (przez wyraźną kolejność szefa spiczastych włosach) używać SPs bezimienny, dobrze - pech! Będziesz musiał trzymać kursory lub spróbować trochę oszukiwać: zmień kod na UDF i utwórz opakowanie SP: D.
CROSS APPLY nie działa dla procedur składowanych, ponieważ nie zwracają zestawów danych, wystarczy podać wyniki. Funkcje zwracają wszystko, dlatego SQL może ich używać tylko podczas korzystania z aplikacji CROSS APPLY. Głosowałem w dół. – Fandango68
@ Fernando68 Wskazałem 3 niezbędne warunki korzystania z aplikacji CROSS APPLY jako rozwiązania na samym początku mojej odpowiedzi, z których trzecia z nich to "można przekonwertować kod na UDF zamiast na SP" –
Ta pętla działa, ale dla mojego SP była powolna.Myślę, że właściwą odpowiedzią jest HLGEM, najlepiej jest napisać lepsze zapytanie zbiorcze.
DECLARE @id INT
SET @id = 0
DECLARE @max INT
SELECT TOP 1 @max = TableID
FROM dbo.Table
ORDER BY TableID desc
-- loop until BREAK
-- this is how you can perform a DO-WHILE loop in TSQL
WHILE (1 = 1)
BEGIN
SELECT
TOP 1 @id = TableID
FROM dbo.Table
WHERE TableID > @id
IF @id IS NOT NULL
BEGIN
-- call you SP here
PRINT @id
END
-- break out of the loop once the max id has been reached
IF @id = @max BREAK
END
- 1. Serwer SQL - czy można wykonać procedurę składowaną
- 2. Jak wdrożyć zarządzaną procedurę składowaną bez użycia Visual Studio?
- 3. Jak zaplanować procedurę składowaną?
- 4. Obracanie kursora bez użycia WinForms
- 5. Sybase IQ - jak wyświetlić procedurę składowaną bez zawijania tekstu?
- 6. Zaszyfruj procedurę składowaną utworzoną przez SqlDependency
- 7. Linq do SQL - czy istnieje sposób odwzorowania metody rozszerzenia na procedurę/procedurę składowaną SQL?
- 8. Jak wywołać procedurę składowaną o niekonwencjonalnych parametrach?
- 9. Jak wywołać procedurę składowaną w widoku?
- 10. Jak wywołać procedurę składowaną przez hibernację?
- 11. Jak automatycznie uruchamiać procedurę składowaną w harmonogramie?
- 12. Zobacz procedurę składowaną/definicję funkcji w MySQL
- 13. Iterowanie bez użycia kursora w MYSQL
- 14. Jak wywołać procedurę składowaną (z parametrami) z innej procedury składowanej bez tabeli tymczasowej
- 15. Jak wykonać procedurę składowaną Oracle za pośrednictwem łącza do bazy danych
- 16. Jak utworzyć procedurę składowaną za pomocą bazy danych H2?
- 17. Jak uruchomić procedurę składowaną za pomocą usługi Azure Automation?
- 18. utwórz procedurę składowaną, jeśli nie istnieje w serwerze sql
- 19. Jak wywołać procedurę składowaną Oracle ze skryptu Excel VBA?
- 20. Czy istnieje sposób przechwytywania zmiennej tabeli w TSQL bez użycia kursora?
- 21. Jak wykonać procedurę przechowywaną w zadaniu agenta SQL?
- 22. Czy mogę wykonać procedurę z domyślnymi parametrami zerowymi?
- 23. Czy można zwrócić wskaźnik do struct bez użycia funkcji malloc?
- 24. Czy użytkownik, który wykonuje procedurę składowaną, która zawiera kwerendę usuwania, musi mieć uprawnienia do usunięcia?
- 25. Wykonaj procedurę przechowywaną w innej procedurze przechowywanej na serwerze SQL
- 26. Czy można zainicjować const struct bez użycia funkcji?
- 27. Czy można zatrzymać javascript w Firebug bez użycia breakpointów?
- 28. Jak wykonać procedurę przechowywaną wewnątrz kwerendy wyboru
- 29. Oracle - wybierz konkretną kolumnę z kursora ref.
- 30. Czy można wykonać takie zapytanie?
Czy to jest całkowicie dokładne? Czy można zamówić przez id bez określania klauzuli group by? –
To nie działa poprawnie. Nie zatrzymuje się po odczytaniu maks. Id. –
-1 Nie działa. Jak powiedział Richard Collette, wybrana składnia jest zepsuta. A jeśli poprawisz składnię, utknie ona w nieskończonej pętli, jak wskazał Tony_Henrich). Dodałem odpowiedź, która ma działającą pętlę, ale była powolna w moim doświadczeniu. –