2011-08-11 38 views
5

Tôi đang viết truy vấn để xoay vòng các phần tử bảng nơi tên cột được tạo động.sử dụng bảng tạm thời trong SQL Azure

SET @query = N'SELECT STUDENT_ID, ROLL_NO, TITLE, STUDENT_NAME, EXAM_NAME, '+ 
      @cols + 
      ' INTO ##FINAL 
      FROM 
      (
       SELECT * 
       FROM #AVERAGES 
       UNION 
       SELECT * 
       FROM #MARKS 
       UNION 
       SELECT * 
       FROM #GRACEMARKS 
       UNION 
       SELECT * 
       FROM #TOTAL 
       ) p 
       PIVOT 
       (
       MAX([MARKS]) 
       FOR SUBJECT_ID IN 
       ('+ 
       @cols +') 
      ) AS FINAL 
      ORDER BY STUDENT_ID ASC, DISPLAYORDER ASC, EXAM_NAME ASC;' 

EXECUTE(@query) 

select * from ##FINAL 

Truy vấn này hoạt động đúng trong cơ sở dữ liệu cục bộ của tôi, nhưng nó không hoạt động trong SQL Azure do bảng tạm thời toàn cầu không được phép ở đó.

Bây giờ nếu tôi thay đổi ##FINA L để #FINAL trong cơ sở dữ liệu địa phương của tôi, nhưng nó mang lại cho tôi lỗi như

tên đối tượng không hợp lệ '#FINAL'.

Tôi làm cách nào để giải quyết vấn đề này?

+0

Tôi không nghĩ rằng vấn đề cụ thể của bạn có thể được giải quyết, vì bạn đang cố gắng xây dựng một thứ gì đó (kết quả được thiết lập với số cột thay đổi) không được SQL hỗ trợ tốt. Trong trường hợp chung, để thực hiện công việc này, bạn phải tạo bảng tạm thời trong phạm vi bên ngoài (tức là trước 'EXECUTE'), nhưng bạn không thể làm điều đó khi bạn không biết bạn đang làm gì sẽ cần. –

+0

Thực ra tôi đã thử nó rồi, tôi đã tạo ra một tên cột có khả năng và đặt tên là @ vào nó. nó không phục vụ bất kỳ mục đích nào vì tôi không thể sử dụng nó trong mệnh đề. tức là CHO SUBJECT_ID TRONG (SELECT cast (subject_id AS NVARCHAR) TỪ #SUBJECT_ID_TABLE) –

+0

Không, điểm là tạo bảng tạm thời '# Final' trước' EXECUTE' - đó là cách duy nhất để có quyền truy cập vào nó trong cả hai phạm vi . Tôi đã chỉ ra một cách có thể làm việc trong câu trả lời của tôi. –

Trả lời

10

Được rồi, sau khi nói rằng tôi không nghĩ rằng nó có thể được thực hiện, tôi có thể có một cách. Đó là xấu xí mặc dù. Hy vọng rằng, bạn có thể chơi với các mẫu dưới đây và áp dụng nó để truy vấn của bạn (mà không cần phải giản đồ và dữ liệu của bạn, nó quá khó khăn cho tôi để cố gắng viết nó):

declare @cols varchar(max) 
set @cols = 'object_id,schema_id,parent_object_id' 

--Create a temp table with the known columns 
create table #Boris (
    ID int IDENTITY(1,1) not null 
) 
--Alter the temp table to add the varying columns. Thankfully, they're all ints. 
--for unknown types, varchar(max) may be more appropriate, and will hopefully convert 
declare @tempcols varchar(max) 
set @tempcols = @cols 
while LEN(@tempcols) > 0 
begin 
    declare @col varchar(max) 
    set @col = CASE WHEN CHARINDEX(',',@tempcols) > 0 THEN SUBSTRING(@tempcols,1,CHARINDEX(',',@tempcols)-1) ELSE @tempcols END 
    set @tempcols = CASE WHEN LEN(@col) = LEN(@tempcols) THEN '' ELSE SUBSTRING(@tempcols,LEN(@col)+2,10000000) END 
    declare @sql1 varchar(max) 
    set @sql1 = 'alter table #Boris add [' + @col + '] int null' 
    exec (@sql1) 
end 

declare @sql varchar(max) 
set @sql = 'insert into #Boris (' + @cols + ') select ' + @cols + ' from sys.objects' 
exec (@sql) 

select * from #Boris 

drop table #Boris 

Họ chính là để tạo ra các bảng temp trong phạm vi bên ngoài, và sau đó phạm vi bên trong (mã chạy trong các câu lệnh EXEC) có quyền truy cập vào cùng một bảng tạm thời. Ở trên làm việc trên SQL Server 2008, nhưng tôi không có một trường hợp Azure để chơi với, do đó, không được thử nghiệm ở đó.

+0

đã thử điều này, nó hoạt động, mặc dù nó trông kinda bẩn k của nó miễn là tôi nhận được kết quả thích hợp. cảm ơn rất nhiều –

1

Nếu bạn tạo bảng tạm thời, bảng hiển thị từ sql động được thực hiện trong spid của bạn, nếu bạn tạo bảng trong sql động, nó không hiển thị bên ngoài đó.

Có một giải pháp thay thế. Bạn có thể tạo một bảng sơ khai và thay đổi nó trong sql động của bạn. Nó đòi hỏi một chút thao tác chuỗi nhưng tôi đã sử dụng kỹ thuật này để tạo ra các bộ dữ liệu động cho tsqlunit.

CREATE TABLE #t1 
(
    DummyCol int 
) 

EXEC(N'ALTER TABLE #t1 ADD foo INT') 

EXEC ('insert into #t1(DummyCol, foo) 
VALUES(1,2)') 

EXEC ('ALTER TABLE #t1 DROP COLUMN DummyCol') 

select *from #t1 
+0

Cột không được biết trước, phải không? –

+0

Đó chỉ là mã chứng minh-khái niệm để chứng minh nguyên tắc. Có nhiều cách để lấy được các cột nhưng trong trường hợp của OP, cols được biết và trong '@ cols'. Một số thao tác sẽ là cần thiết để dịch '@ cols' thành câu lệnh thay đổi. Damien_The_Unbeliever đã viết một ví dụ hoàn chỉnh hơn về phương pháp này. –

+0

Xin lỗi. Bạn đúng rồi. –

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