2013-03-04 37 views
13

Tôi biết rằng các truy vấn sau đây sẽ kéo xuống tập hợp kết quả từ một máy chủ được liên kết:OPENQUERY khác với SELECT và INSERT như thế nào?

SELECT * FROM openquery(DEVMYSQL, 
    'SELECT event_id, people_id, role_id, rank, last_updated FROM event_cast') 

Tuy nhiên, đây là trường hợp tương tự khi nói đến chèn? Nó sẽ kéo xuống tập kết quả hoặc nó sẽ chỉ nhận được thông tin cột?

INSERT INTO openquery(DEVMYSQL, 
    'SELECT event_id, people_id, role_id, rank, last_updated FROM event_cast') 

Nếu trước đây, điều này rất không hiệu quả. Tôi có nên giới hạn tập kết quả được trả lại và điều này có ảnh hưởng đến số INSERT của tôi không?

Đây thực chất là câu hỏi về cách OPENQUERY hoạt động khi nói đến SELECTINSERT.

Tôi đánh giá cao sự giúp đỡ nào.

Trả lời

10

Không chắc chắn bạn cố gắng làm gì với INSERT của mình.

Cú pháp đúng (nếu bạn muốn chèn trên máy chủ REMOTE) nên

INSERT into openquery(MyServer, 'dbo.event_cast') values ('','') 

Các chọn chỉ trì hoãn chèn của bạn lấy những gì bao giờ chọn truy vấn trả về (vô ích) mà không đem lại cho bạn thông tin bổ sung . Ngoài ra, với OPENQUERY bạn có thể sử dụng cú pháp này, chính xác hơn, cho chèn:

INSERT into myserver.mydatabase.dbo.event_Cast values('','') 

Tuy nhiên, nếu bạn đang cố gắng để chèn vào máy chủ ĐỊA PHƯƠNG các giá trị lấy được chọn cú pháp nên là:

INSERT into dbo.my_localtable SELECT * FROM openquery(DEVMYSQL, 'SELECT event_id, people_id, role_id, rank, last_updated FROM event_cast') 

Và có, câu sẽ chèn các giá trị, không chỉ thông tin cột.

Nếu bạn chỉ muốn sao chép bảng cục bộ đơn giản

SELECT top 1 * into new_local_event_cast FROM openquery(DEVMYSQL, 'SELECT event_id, people_id, role_id, rank, last_updated FROM event_cast'); 
TRUNCATE TABLE new_local_event_cast; 

sẽ đủ

+2

Chỉ cần thông tin: Cú pháp đặt tên bốn phần trong ví dụ thứ hai chỉ hoạt động nếu loại Máy chủ được Liên kết đã được đăng ký vào Giao dịch Phân tán. (Hầu hết là, chỉ cần một hình ảnh xác thực.) –

+0

Với truy vấn đầu tiên của bạn, bạn xác định các cột để chèn vào mà không chỉ định các cột thông qua một lựa chọn như thế nào? – Abs

+0

Tôi thực hiện việc chèn hoàn chỉnh chỉ để lại các cột có dữ liệu nhận dạng hoặc dữ liệu mặc định (hầu hết thời gian tôi cũng ghi dữ liệu mặc định). Thông thường là nhanh hơn để cung cấp cho toàn bộ recordset để chèn khi nó viết nó như một đoạn dữ liệu. Các openquery giả định rằng các cols là trong thứ tự chèn (như chèn bình thường làm). True: nếu bạn cần phải especify cols liên tiếp bạn cần phải sử dụng lựa chọn, nhưng với chi phí hiệu suất – Zelloss

4

Trường hợp SELECT sẽ trả về các bản ghi, INSERT sẽ không trả lại tập kết quả ngoại trừ số lượng bản ghi bị ảnh hưởng. Điều này có thể bị chặn bằng cách sử dụng SET NOCOUNT ON; tuy nhiên, tôi không chắc chắn liệu sự đàn áp có liên quan đến khả năng hiển thị hay số lượng hàng thực sự đến.

INSERT INTO OPENQUERY(MYSERVER, 'SELECT [Drive_Letter] ,[MBFree],[Server] FROM [Blah].[dbo].[SQL_Drives]') 
    SELECT 'X', 2, 'MyServer' 

(1 row(s) affected) 

Đối với hồ sơ được trả về từ INSERT, cách duy nhất để thực hiện điều đó xảy ra là sử dụng mệnh đề OUTPUT. Máy khách sẽ không có quyền truy cập vào các hàng OUTPUT INSERTED do đó không thể trả về các hàng này. Nếu bạn cố gắng chạy những điều sau, bạn sẽ nhận được thông báo lỗi:

INSERT INTO OPENQUERY(MYSERVER, 'SELECT [Drive_Letter] ,[MBFree],[Server] FROM [BLAH].[dbo].[SQL_Drives]') 
OUTPUT INSERTED.* 
SELECT 'X', 2, 'MyServer' 

Msg 405, Level 16, State 1, Line 1 
A remote table cannot be used as a DML target in a statement which includes an OUTPUT clause or a nested DML statement. 


-- EDIT RESULTS OF PROFILER ---------------------------  


-- Statements that occured on server called through OPENQUERY 
    exec sp_cursoropen @p1 output,N'SELECT [Drive_Letter] ,[MBFree],[Server] FROM [MyServer].[dbo].[SQL_Drives]',@p3 output,@p4 output,@p5 output 
    select @p1, @p3, @p4, @p5 

    exec sp_cursor 180150009,4,0,N'[MyServer].[dbo].[SQL_Drives]',@Drive_Letter='X',@MBFree=2,@Server='MyServer' 


--Statements that occured on client 
    INSERT INTO OPENQUERY(MyServer, 'SELECT [Drive_Letter] ,[MBFree],[Server] FROM [MyServer].[dbo].[SQL_Drives]') 
    SELECT 'X', 2, 'MyServer' 
+0

Khi tôi đề cập đến 'INSERT', tôi thực sự đang nói về' SELECT' trong 'OPENQUERY'. Truy vấn này được thực hiện trên máy chủ được liên kết và sau đó 'INSERT' sẽ được thực thi trên máy chủ cục bộ. Tuy nhiên, máy chủ SQL sẽ nhận ra rằng nó là một 'INSERT' và do đó không trả về tập kết quả từ máy chủ được liên kết? – Abs

+0

Tôi chỉ chạy các câu lệnh tương tự và xem hồ sơ trên mỗi đầu. Các kết quả ở trên, khiến tôi tin rằng lệnh SELECT chỉ xảy ra trên máy chủ đang được OPENQUERY gọi và SELECT hoạt động nhiều hơn như một khuôn mẫu cho phần chèn hơn bất kỳ thứ gì khác. – PseudoToad

1

Khi bạn sử dụng OPENQUERY để thực hiện một INSERT, nó sẽ thực hiện SELECT đầu tiên và vứt bỏ các kết quả. Nó sử dụng siêu dữ liệu cột từ tập hợp kết quả để xác định cách gửi lệnh INSERT. Vì lý do đó, bạn nên luôn thêm where 1=0 vào cuối SELECT.

Từ SQL Server để MySQL cú pháp thích hợp là:

insert into openquery(MYSQLDEV, 'select * from insert_test where 1=0') values ('test'); 

Nếu bạn kích hoạt bản ghi truy vấn chung về phía MySQL bạn sẽ thấy các lệnh này đến từ SQL Server:

SET NAMES utf8 
SET character_set_results = NULL 
SET SQL_AUTO_IS_NULL = 0 
set @@sql_select_limit=1 
select * from insert_test where 1=0 
select * from insert_test where 1=0 
INSERT INTO `database`.`insert_test`(`column`) VALUES ('test') 

Vì vậy, bạn có thể thấy rằng lựa chọn đang được thực hiện hai lần. Nếu không có where 1=0, tất cả các hàng sẽ được máy chủ MySQL trả về.

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