2012-06-29 11 views
7

Próbuję utworzyć funkcję zgodnie z moimi wymaganiami.Tworzenie, upuszczanie i wstawianie tabeli tymczasowej w zdefiniowanej przez użytkownika funkcji

Ale kiedy tworzę lub spadek #tempTable, to daje błąd jako:

nieprawidłowym wykorzystaniem bocznej dokonania operatora „obiektu upuść” w funkcji

Moje rozumienie jest że nie możemy wykonywać operacji na create, drop ani na .

Czy to prawda?

My SQL:

CREATE FUNCTION [dbo].[RT_ResultFunction] 
(
    Id VARCHAR(4000) 
) 
RETURNS @RT_ResultFunction TABLE 
( 
    Id VARCHAR(20) 
    , Name varchar(20) 
    ,Balance Int 
) 
AS 
BEGIN 
    IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL 
     DROP TABLE #tempTable 

    SELECT Id, COUNT(Balance) 
    INTO #tempTable 
    'Balance' FROM Table1 

    INSERT @RT_ResultFunction 
     SELECT T1.ID,T1,NAME,T2,Balance 
     FROM Table2 T1, 
       #tempTable T2 
     WHERE T1.ID = T2.ID 

    RETURN 
END 
+1

Nie rozumiem twojego SQL. Jak wybrać z #tempTable po upuszczeniu go - nigdy go nie odtworzyć. –

+0

Proszę znaleźć zaktualizowany post –

+0

Jeśli chcesz pomóc w rozwiązaniu tego problemu, proszę wyjaśnij punkt # zwolnienia w ramach funkcji. Co zrobić z parametrem Id. –

Odpowiedz

19

Zgadza się - nie można mieć niepożądane dokonania stwierdzenia:

stąd: http://msdn.microsoft.com/en-us/library/aa175085(v=sql.80).aspx

Sprawozdanie w bloku begin ... END nie może mieć jakiekolwiek skutki uboczne. Efekty uboczne funkcji to wszelkie trwałe zmiany w stanie zasobu , które ma zakres poza funkcją, taką jak modyfikacja , do tabeli bazy danych. Jedynymi zmianami, które można wprowadzić za pomocą instrukcji w funkcji, są zmiany obiektów lokalnych dla funkcji , takich jak lokalne kursory lub zmienne. Modyfikacje tabel bazy danych, operacje na kursorach, które nie są lokalne dla funkcji , wysyłanie wiadomości e-mail, próba modyfikacji katalogu i generowanie zestawu wyników, który jest zwracany użytkownikowi, są przykładami działań, których nie można wykonać na przykładach: . funkcja.

Co będzie można znaleźć, nawet bez wyciągu DROP, jest to, że każda próba uzyskania dostępu do temp tabeli daje komunikat (np SELECT ... INTO #TMP):

nie można uzyskać dostępu do tabel tymczasowych od wewnątrz funkcję

Jako @Dems zwraca uwagę, można używać zmiennych tabeli. Ponieważ są to zmienne, są one zdefiniowane w funkcji, a zatem nie mają skutków ubocznych.

Twoja funkcja może działać jako:

... 

BEGIN 
    DECLARE @tempTable table (id varchar(20), rows int) 

    insert @tempTable 
    SELECT Id, COUNT(Balance) 
    FROM Table1 

    INSERT @RT_ResultFunction 
     SELECT T1.ID,T1,NAME,T2,Balance 
     FROM Table2 T1, 
       @tempTable T2 
     WHERE T1.ID = T2.ID 

    RETURN END 

nie testowano albo coś, ale masz sens.

+3

Ale można używać zmiennych tabeli. Który byłby przydatny fakt, aby dodać do twojej odpowiedzi, aby pomóc OP w rozwiązaniu jego problemu * (zamiast tylko wiedzieć, dlaczego to jest problem) *;) – MatBailie

+0

@Dems: Dobry punkt - zaktualizowany o więcej informacji. –

+0

Po przeczytaniu dokumentacji MSDN, zadałem sobie pytanie: czy możliwe jest modyfikowanie rzeczywistych danych z tabeli ('INSERT' /' UPDATE'/'DELETE') poprzez wywołanie' Procedury składowanej' w swojej 'funkcji'? Przypuszczam, że nie możesz, ale wolałbym się upewnić, że pojawi się błąd. Czy możesz mi powiedzieć, czy to wiesz? :) –

2

Nie mam pojęcia, dlaczego potrzebujesz tabeli #temp w tej funkcji lub dlaczego jest to przede wszystkim wielostronna telewizja TVF.Poniższa będzie dużo bardziej wydajny (choć nie rozumiem cel parametru @Id):

CREATE FUNCTION [dbo].[RT_ResultFunction] 
(
    @Id VARCHAR(4000) 
) 
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
    RETURN 
    (
    SELECT T2.ID, T2.NAME, T1.Balance 
    FROM 
    (
     SELECT ID, Balance = COUNT(Balance) 
     FROM dbo.Table1 
     GROUP BY ID 
    ) AS T1 
    INNER JOIN dbo.Table2 AS T2 
    ON T1.ID = T2.ID 
); 

Jak Jon zauważył, myślę może to również być ponownie zapisać w następujący sposób, a to faktycznie, jak zacząłem pisać, ale nie mam możliwości, aby potwierdzić, czy którykolwiek z tych faktycznie zwraca dane próbujesz wrócić:

CREATE FUNCTION [dbo].[RT_ResultFunction] 
(
    @Id VARCHAR(4000) 
) 
RETURNS TABLE 
WITH SCHEMABINDING 
AS 
    RETURN 
    (
    SELECT T2.ID, T2.NAME, Balance = COUNT(T1.Balance) 
    FROM dbo.Table1 AS T1 
    INNER JOIN dbo.Table2 AS T2 
    ON T1.ID = T2.ID 
    GROUP BY T2.ID, T2.NAME 
); 
+0

Prawda - stół tymczasowy jest w tym przypadku trochę "luksusem", ale jest to przydatny punkt do objęcia w każdym przypadku. (potrzebujesz również aliasu na wewnętrznej kolumnie count). –

+0

@Jon ID i nazwa pochodzą z różnych tabel. Nie znam schematu ani danych, więc starałem się zachować zgodność z pierwotnym zapytaniem. –

0

usunąć # zamiast użyć @ nie testowałem inny aspekt

Powiązane problemy