2011-01-28 17 views
6

Tło: Istnieje procedura składowana, która "wypełnia" tabelą tymczasową o danej nazwie. Procedura ma charakter ogólny, ponieważ kontroluje schemat tabeli tymczasowej, a następnie wykonuje różne "rzeczy" w zależności od schematu. Rozumiem, że jest to trochę dziwne, ale niechętnie go zmieniam, ponieważ wszystko działa dobrze w większości sytuacji, z wyjątkiem ....Dlaczego SQL Server uważa, że ​​tabela Temp istnieje już wtedy, gdy nie istnieje?

Jeśli mam procedurę przechowywaną, która tworzy dwa różne schematy dla tabeli tymczasowej z to samo imię. Logicznie tworzy tylko jedną tabelę tymczasową w zależności od gałęzi IF. Problem polega na tym, że gdy sproc jest sprawdzana przez SQL Server wydaje się, że jest ona oceny obu stron IF

Więc to SQL nie powiedzie (co ma sens, jeśli to sprawdzanie składni SQL.):

IF (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL 
    ) 
END 
ELSE 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL, 
     c BIGINT NOT NULL 
    ) 
END 

--exec SomeProcedureWhichDoesStuffWith#Test 

DROP TABLE #test 

z powodu następującego błędu:

Msg 2714, Level 16, State 1, Line 14
There is already an object named '#test' in the database.

Żadna kombinacja tabeli rozwijanej wewnątrz IFS (przed lub po tabela tworzyć DDL) wydaje się spełniać sprawdzania sQL.

Jakieś pomysły, jak mogę to zrobić? Czy mogę na przykład powiedzieć SQL, aby nie wykonywał sprawdzania składni i po prostu akceptował sproc jak jest?

Odpowiedz

6

To ograniczenie. Dynamiczny SQL również nie zadziała, ponieważ #tmp zostanie utworzony w nowej sesji i natychmiast utracony. Aby uzyskać dokładny urywek Jak widać, to robi to samo

CREATE TABLE #test 
(
    a BIGINT NOT NULL, 
    b BIGINT NOT NULL 
) 

IF not (1=1) 
    ALTER TABLE #test ADD c BIGINT NOT NULL 

Nie może być dwóch TWORZENIE .. #name obrębie tej samej partii, ale to będzie także działać w ogólnej postaci

IF (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL 
    ); 
END 
GO 

IF NOT (1=1) 
BEGIN 
    CREATE TABLE #test 
    (
     a BIGINT NOT NULL, 
     b BIGINT NOT NULL, 
     c BIGINT NOT NULL 
    ) 
END 
0

ponieważ ja dont sql 2008, nie mogę go przetestować. jednak z tego co wiem, jest to problem parsera jawnie z tabelami tymczasowymi. tak samo będzie działać dobrze z normalnych tabel

to rozwiązać, po prostu podzielić swój kod z logicznych wypowiedzi GO

idealnie: sprawdzenia istnienia tabel tymczasowych przed tworzyć tabele tymczasowe, upuść, jeśli istnieją, ogień iść, czy tworzenie tabel tymczasowych znów wystrzelić odejść, wtedy każdy postprocessing, ogień iść wreszcie upuść je ponownie i ogień ostatni iść


możesz również spróbować użyć zmienna tabeli zamiast tabel temp, jeśli powyższe nie rozwiąże go dla Ciebie

+0

Tak dzięki za informacje. Niestety tworzy on tabele w sproc, więc musi być w tej samej partii (więc nie ma go GO). –

0

Zawsze możesz „oszukiwać”:

DECLARE @SQL VARCHAR(200) 

IF (1=1) 
BEGIN 
    SET @SQL = 'CREATE TABLE #Temp  ' + 
       '(      ' + 
       ' a BIGINT NOT NULL, ' + 
       ' b BIGINT NOT NULL ' + 
       ')      ' 
END 
ELSE 
BEGIN 
    SET @SQL = 'CREATE TABLE #Temp  ' + 
       '(      ' + 
       ' a BIGINT NOT NULL, ' + 
       ' b BIGINT NOT NULL, ' + 
       ' c BIGINT NOT NULL ' + 
       ')      ' 
END 

EXEC SP_EXECUTESQL @SQL 
+0

To nie zadziała, ponieważ natychmiast zniknie z zakresu i nie będzie użyteczne w zewnętrznym skrypcie. Musiałaby to być globalna tabela tymczasowa lub wszystkie zastosowania tabeli tymczasowej wymagałyby dynamicznego kodu SQL. –

2

Zamiast # # # test, należy użyć pełnej nazwy. Na przykład:

[tempdb].[dbo].[temptable] 

Nauczyłem się tej małej sztuczki tutaj Insert result of executing dynamic query into a table.

IntelliSense będzie skarżyć, ale nadal będzie można utworzyć lub zmienić procedurę przechowywaną.

Kiedy z nim zrobić, należy go upuszczać:

DROP TABLE [tempdb].[dbo].[temptable] 
Powiązane problemy