2012-11-05 27 views
7

tại sao mã công việc này mà không có vấn đề:Sự khác nhau giữa Bàn Bàn Temp

drop table t1 
select * into t1 from master..spt_values 
drop table t1 
select * into t1 from master..spt_values 

Output

Msg 3701, Level 11, State 5, Line 1 
Cannot drop the table 't1', because it does not exist or you do not have permission. 

(2508 row(s) affected) 

(2508 row(s) affected) 

nhưng mã này không:

drop table #t1 
select * into #t1 from master..spt_values 
drop table #t1 
select * into #t1 from master..spt_values 

Output

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

sự khác nhau giữa Bảng và Bảng tạm thời trong mã này là gì?

+3

Câu hỏi hay. Để minh họa tốt hơn điểm của bạn [this SQLFiddle] (http://sqlfiddle.com/#!3/d41d8/5748) không hoạt động, nhưng thay thế bằng các bảng bình thường thì – RichardTheKiwi

+4

[Giải thích cho hành vi ở đây] (http: //sqlblog.com/blogs/michael_zilberstein/archive/2008/08/28/Name-resolution-in-SQL-Server.aspx) Đối với 't1' các câu lệnh có thể được biên dịch trả chậm nhưng đây không phải là trường hợp cho' # t1 ' –

+0

Cũng giống như một lưu ý phụ" [DROP TABLE và CREATE TABLE không nên được thực hiện trên cùng một bảng trong cùng một lô. Nếu không, một lỗi không mong muốn có thể xảy ra.] (http://msdn.microsoft.com/en-us/ thư viện/ms173790.aspx) " –

Trả lời

4

Để đối phó với tất cả các câu trả lời sai khác, cách chính xác để kiểm tra cho một bảng #temp là

if object_id('tempdb..#temp') is not null 
    drop table #temp; 


Dưới đây là một interesting article về giai đoạn biên dịch và thực hiện giai đoạn vui vẻ với các bảng #temp.


Đây là tài liệu tham khảo MSDN cho Deferred Name Resolution (DNR). Để hỗ trợ cho việc tạo các thủ tục lưu trữ và các lô lệnh, Deferred Name Resolution được thêm vào trong SQL Server 7. Trước đó (Sybase), sẽ rất khó để tạo và sử dụng các bảng trong một lô mà không cần sử dụng nhiều SQL động.

Tuy nhiên, nếu tên hiện có tồn tại, SQL Server sẽ tiếp tục và kiểm tra các khía cạnh khác của câu lệnh, chẳng hạn như tên cột của đối tượng bảng. DNR không bao giờ được mở rộng tới các biến hoặc các đối tượng tạm thời (#)/(##) và khi các hàm bảng giá trị nội tuyến được thêm vào trong SQL Server 2000, DNR không được mở rộng cho chúng vì mục đích của DNR chỉ để giải quyết -statement lô vấn đề. Không được nhầm lẫn, nội tuyến các hàm có giá trị bảng không hỗ trợ DNR; đa tuyên bố TVF.

Cách giải quyết là KHÔNG sử dụng mẫu đó và thay vào đó tạo bảng đầu tiên và chỉ một lần.

-- drop if exists 
if object_id('tempdb..#t1') is not null 
    drop table #t1; 
-- create table ONCE only 
select * into #t1 from master..spt_values where 1=0; 
-- .... 
-- populate 
insert #t1 
select * from master..spt_values 
-- as quick as drop 
truncate table #t1; 
-- populate 
insert #t1 
select * from master..spt_values 
-- as quick as drop 
truncate table #t1; 

-- clean up 
drop table #t1; 
+0

nó không hoạt động, tôi kiểm tra tất cả các cách này trước khi yêu cầu ở đây ... – NeatAttack

+0

@Neat Nếu bạn có nghĩa là trong bối cảnh của lô mà không có' GO', thì có nó doesn ' t làm việc để giải quyết vấn đề thời gian biên dịch. Tôi đang đưa ra câu trả lời bởi vì tất cả các bài kiểm tra khác chỉ đơn giản là sai. – RichardTheKiwi

+0

Có lý do nào cho các kết nối được kết hợp ở đây không? Tất cả mọi thứ tôi đã thấy trực tuyến nói rằng họ đang giảm xuống khi kết nối được thiết lập lại. –

Các vấn đề liên quan