2011-01-28 6 views
6

Bối cảnh: Có một quy trình được lưu trữ thực hiện "nội dung" với bảng tạm thời của tên đã cho. Thủ tục là chung chung ở chỗ nó kiểm tra lược đồ của bảng tạm thời và sau đó thực hiện các "công cụ" khác nhau tùy thuộc vào lược đồ. Tôi hiểu rằng điều này hơi kỳ lạ nhưng tôi không muốn thay đổi nó vì tất cả đều hoạt động tốt trong hầu hết các trường hợp, ngoại trừ ....Tại sao SQL Server cho rằng Bảng tạm thời đã tồn tại khi nó không?

Nếu tôi có một thủ tục lưu trữ tạo hai lược đồ khác nhau cho bảng tạm thời cùng tên. Về mặt logic nó chỉ tạo ra một bảng tạm thời tùy thuộc vào nhánh của IF. Vấn đề là khi SPROC được kiểm tra bởi SQL Server nó có vẻ như nó đang đánh giá cả hai mặt của NẾU

Vì vậy, SQL này không thành công (trong đó có ý nghĩa nếu nó được kiểm tra cú pháp 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 

với các lỗi sau:

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

Không kết hợp thả bảng bên trong IFS (trước hoặc sau khi bảng tạo DDL) dường như đáp ứng các checker sql.

Bất kỳ ý tưởng nào về cách tôi có thể thực hiện việc này? Tôi có thể, ví dụ, nói với SQL để không thực hiện kiểm tra cú pháp và chỉ chấp nhận sproc như là?

Trả lời

6

Đó là giới hạn. SQL động sẽ không hoạt động vì #tmp sẽ được tạo trong phiên mới và bị mất ngay lập tức. Đối với đoạn mã chính xác như hình, điều này cũng làm như vậy

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

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

Không thể có hai CREATE .. #name trong cùng một lô, nhưng điều này cũng sẽ làm việc theo hình thức chung

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

kể từ khi tôi không có sql 2008, tôi không thể kiểm tra nó. Tuy nhiên theo như tôi biết, đây là một vấn đề phân tích cú pháp một cách rõ ràng với các bảng tạm thời. cùng sẽ làm việc tốt với các bảng bình thường

để sắp xếp này ra, chỉ cần tách mã của bạn với báo cáo GO logic

lý tưởng: kiểm tra sự tồn tại của bảng tạm thời trước khi bạn tạo bảng tạm thời của bạn, thả chúng nếu chúng tồn tại, bắn một đi, làm việc tạo ra các bảng tạm thời một lần nữa, bắn một đi, sau đó bất kỳ xử lý bưu điện, bắn một đi, cuối cùng thả chúng một lần nữa và bắn đi cuối cùng


bạn cũng có thể muốn thử và sử dụng biến bảng thay vì bảng tạm thời nếu ở trên không giải quyết được cho bạn

+0

Có cảm ơn cho thông tin. Thật không may nó tạo ra các bảng trong một sproc, do đó, nó có được trong cùng một lô (vì vậy nó không phải là đi trên GO). –

0

Bạn luôn có thể "ăn gian":

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

Điều đó sẽ không hoạt động vì nó sẽ nằm ngoài phạm vi ngay lập tức và không thể sử dụng được trong kịch bản bên ngoài. Nó cần phải là một bảng tạm thời toàn cục hoặc tất cả các tập quán của bảng tạm thời sẽ cần phải có trong SQL động. –

2

Thay vì #test, sử dụng tên đầy đủ. Ví dụ:

[tempdb].[dbo].[temptable] 

Tôi đã học được mẹo nhỏ này tại đây Insert result of executing dynamic query into a table.

Intellisense sẽ khiếu nại nhưng bạn vẫn có thể tạo hoặc thay đổi thủ tục được lưu trữ.

Khi thực hiện với nó, hãy chắc chắn để thả nó:

DROP TABLE [tempdb].[dbo].[temptable]