2012-06-29 37 views
7

Tôi đang cố tạo một hàm theo yêu cầu của mình.Tạo, thả và chèn một bảng tạm thời vào một hàm do người dùng định nghĩa

Tuy nhiên, khi đang tạo ra hoặc thả #tempTable, nó được đưa ra một lỗi như:

sử dụng không hợp lệ của một nhà điều hành phụ ảnh hưởng 'thả đối tượng' trong một hàm

hiểu biết của tôi là chúng tôi không thể có các hoạt động create, drop hoặc insert hoạt động trên #temptable trong một chức năng.

Điều đó có đúng không?

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

Bit nhầm lẫn về SQL của bạn. Cách bạn chọn từ #tempTable sau khi bạn đã xóa nó - nó không bao giờ được tạo lại. –

+0

Vui lòng tìm bài viết cập nhật –

+0

Nếu bạn muốn trợ giúp giải quyết vấn đề này, vui lòng giải thích điểm của #temptable bên trong hàm. Ngoài ra phải làm gì với thông số Id. –

Trả lời

19

Đó là đúng - bạn không thể có mặt thực báo cáo:

Từ đây: http://msdn.microsoft.com/en-us/library/aa175085(v=sql.80).aspx

Các báo cáo trong một khối BEGIN ... END không thể có bất kỳ tác dụng phụ nào. Tác dụng phụ của chức năng là bất kỳ thay đổi vĩnh viễn nào đối với trạng thái tài nguyên có phạm vi bên ngoài chức năng, chẳng hạn như sửa đổi thành bảng cơ sở dữ liệu. Những thay đổi duy nhất có thể được thực hiện bởi các câu lệnh trong hàm là các thay đổi đối với các đối tượng cục bộ với hàm , chẳng hạn như các con trỏ cục bộ hoặc các biến. Sửa đổi đối với các bảng cơ sở dữ liệu , hoạt động trên con trỏ không phải là cục bộ đối với hàm , gửi e-mail, sửa đổi danh mục và tạo tập kết quả được trả lại cho người dùng là ví dụ về các hành động không thể thực hiện được một hàm.

gì bạn sẽ tìm thấy, ngay cả khi không tuyên bố DROP của bạn, đó là bất kỳ nỗ lực để truy cập vào một bảng tạm thời sẽ cung cấp cho bạn thông điệp (chẳng hạn như một SELECT ... INTO #TMP):

Không thể truy cập bảng tạm thời từ bên trong một hàm

Như @Dems chỉ ra, bạn có thể sử dụng các biến bảng. Bởi vì đây là những biến, chúng được đặt trong phạm vi hàm, và do đó không có tác dụng phụ.

Chức năng của bạn có thể chạy như:

... 

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 

Không thử nghiệm hoặc bất cứ điều gì, nhưng bạn sẽ có được các ý chính.

+3

Nhưng bạn có thể sử dụng các biến bảng. Đó sẽ là một thực tế hữu ích để thêm vào câu trả lời của bạn để hỗ trợ OP giải quyết vấn đề của mình * (thay vì chỉ biết lý do tại sao đó là vấn đề) *;) – MatBailie

+0

@Dems: Good point - updated with more info. –

+0

Sau khi tôi đọc tài liệu MSDN, tôi tự hỏi: liệu có thể sửa đổi dữ liệu thực từ một bảng ('INSERT' /' UPDATE'/'DELETE') bằng cách gọi' Thủ tục lưu trữ' trong 'hàm' của bạn? Tôi cho rằng bạn không thể, nhưng tôi muốn chắc chắn rằng một lỗi sẽ được tạo ra. Bạn có thể cho tôi biết nếu bạn biết điều đó không? :) –

2

Tôi không biết tại sao bạn cần bảng #temp trong chức năng này hoặc tại sao đó là TVF đa tuyên bố ngay từ đầu.Sau đây sẽ được nhiều hiệu quả hơn (mặc dù tôi không hiểu mục đích của tham số @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 
); 

Như Jon chỉ ra, tôi nghĩ nó cũng có thể được viết lại như sau, và nó thực sự làm thế nào tôi bắt đầu viết nó, nhưng tôi không có cách nào để xác nhận nếu một trong những thực sự trả về dữ liệu bạn đang cố gắng để trở lại:

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

True - bảng tạm thời là một chút "sang trọng" trong trường hợp này, nhưng nó là một điểm hữu ích để trang trải trong mọi trường hợp. (bạn cũng cần một bí danh trên col bên trong). –

+0

@ ID và Tên đến từ các bảng khác nhau. Tôi không biết lược đồ hoặc dữ liệu vì vậy tôi đã cố gắng giữ đúng với truy vấn ban đầu. –

0

Remove # thay vì sử dụng @ tôi đã không kiểm tra khía cạnh khác

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