CHỌN VÀO Dự trữ tên #Object trong TempDB trước thời gian chạy?


8

Kết hợp một công cụ quickie để giúp gỡ lỗi, tôi gặp phải một lỗi dường như là một lỗi trong trình biên dịch.

create proc spFoo
    @param bit
as
begin
    if @param = 0
    begin 
        select * 
        into #bar
        from [master].dbo.spt_values
        -- where number between ...
    end
    else
    begin
        select top 10 * 
        into #bar
        from [master].dbo.spt_values
        order by newid();
    end;
end;

Cố gắng ở trên trả về lỗi sau

Msg 2714, Cấp 16, Trạng thái 1, Thủ tục spFoo, Dòng 19
Đã có một đối tượng có tên '#bar' trong cơ sở dữ liệu.

Theo nghĩa có thể đọc được của con người, Proc dường như vẫn ổn: chỉ có một select intocâu lệnh sẽ được thực thi kể từ khi chúng được bọc bên trong các if-elsekhối. Mặc dù vậy, máy chủ SQL không thể xác nhận rằng các câu lệnh được loại trừ một cách hợp lý với nhau. Có lẽ khó hiểu hơn là lỗi vẫn còn khi drop table #foođược đặt bên trong khối if-other (mà người ta giả định sẽ báo cho trình biên dịch phân bổ tên đối tượng) như bên dưới.

create proc spFoo
    @param bit
as
begin
    select top 1 * 
    into #bar
    from [master].dbo.spt_values

    if @param = 0
    begin 
        drop table #bar;

        select * 
        into #bar
        from [master].dbo.spt_values
        -- where number between ...
    end
    else
    begin
        drop table #bar;

        select top 10 * 
        into #bar
        from [master].dbo.spt_values
        order by newid();
    end;
end;

Bản thân Proc cũng ổn. Tôi mút nó và viết create table #foo( ... )insert #foo ( ... )phát biểu, tôi đã cố gắng bỏ qua với select * into cú pháp. Tại thời điểm này, tôi chỉ đang cố gắng để hiểu lý do tại sao trình biên dịch xuất hiện trong tôi với cú pháp của kẻ lười biếng. Điều duy nhất tôi có thể nghĩ là lệnh DDL bảo lưu tên đối tượng IN TEMPDB .

Tại sao chữ đậm?

create proc spIck
as
begin
    create table #ack ( col1 int );
    drop table #ack;
    create table #ack ( colA char( 1 ) );
    drop table #ack;
end;

Điều này không thành công với mã lỗi như trên. Nhưng sau đây ...

create proc spIck
as
begin
    create table ack ( col1 int );
    drop table ack;
    create table ack ( colA char( 1 ) );
    drop table ack;
end;

... Thành công. Điều tương tự như sau ở trên với nỗ lực ban đầu. Vì thế...

Câu hỏi của tôi là đây

Sự khác biệt (và tại sao nó hiện diện) trong bảo lưu tên đối tượng cho TempDBcác đối tượng trái ngược với cơ sở dữ liệu người dùng. Không có tài liệu tham khảo Xử lý truy vấn logic hay tham chiếu lệnh DDL nào tôi đã xem xét xuất hiện để giải thích điều này.


1
Ảnh chụp màn hình này từ "Hướng dẫn của bậc thầy về các thủ tục lưu trữ, XML và HTML của máy chủ SQL" (trên Google Sách) có vẻ phù hợp và cho thấy đây là cách nó hoạt động kể từ 7.0 i.stack.imgur.com/8pDGT.png
Martin Smith

Xuất hiện ở trang 6 (FYI cho bất kỳ ai đến với chủ đề sau).
Peter Vandivier

Câu trả lời:


6

Điều này không liên quan gì đến việc đặt tên đối tượng trong TempDB hoặc bất cứ điều gì liên quan đến thời gian chạy. Đây chỉ đơn giản là trình phân tích cú pháp không thể theo các đường dẫn logic hoặc mã đảm bảo rằng mã của bạn không thể cố gắng tạo bảng đó hai lần. Lưu ý rằng bạn nhận được chính xác lỗi (không phải thời gian chạy!) Nếu bạn chỉ cần nhấp vào nút Parse ( Ctrl+ F5). Về cơ bản, nếu bạn có điều này:

IF 1=1 
  CREATE TABLE #foo(id1 INT);
ELSE
  CREATE TABLE #foo(id2 INT);

Trình phân tích cú pháp thấy điều này:

  CREATE TABLE #foo(id1 INT);
  CREATE TABLE #foo(id2 INT);

Tại sao nó không hoạt động theo cách này cho các bảng thực tế , bao gồm các bảng người dùng thực tế được tạo trong TempDB (lưu ý rằng nó cũng không phải là cơ sở dữ liệu cụ thể)? Câu trả lời duy nhất tôi có thể đề xuất là trình phân tích cú pháp có một bộ quy tắc khác cho các bảng #temp (cũng có rất nhiều sự khác biệt khác). Nếu bạn muốn có lý do cụ thể hơn, bạn sẽ cần mở một vụ kiện với Microsoft và xem họ có cung cấp cho bạn thêm thông tin chi tiết nào không. Tôi đoán là bạn sẽ được nói: "đây là cách nó hoạt động."

Một số thông tin thêm trong những câu trả lời này:


Trên thực tế, " đây là cách nó hoạt động " chính xác là phản ứng mà họ có. Ôi
chà
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.