2013-03-04 20 views
13

Ben aşağıdaki sorgu bağlantılı bir sunucudan sonuç kümesini aşağı çekecek farkındayım: takmadan bunu geldiğinde AncakOPENQUERY SELECT ve INSERT için nasıl farklıdır?

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

, bu aynı durumda? Sonuç kümesini aşağı çekecek mi yoksa sadece sütun bilgisini alacak mı?

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

Eğer eski ise, o zaman bu çok verimsizdir. Sonuç kümesini iade etmem gerekir mi ve bu benim INSERT etki mi?

Bu, temel olarak OPENQUERY'un SELECT ve INSERT sürümleriyle ilgili nasıl çalıştığıyla ilgili bir sorudur.

Yardımlarınız için minnettarım.

cevap

10

Eğer INSERT ile gerçekleştirmek için deneyin ne olduğundan emin. (Eğer UZAKTAN sunucuda eklemek istiyorsanız) olmalıdır

doğru sözdizimi

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

seçeneğini yalnızca almak ekinizi geciktirir her ne size ek bilgi vermeden (boşuna) seçme sorgusu döndürür . sözdizimi seçmek YEREL sunucusuna tarafından alınan değerler eklemeye çalışıyorsanız olmalıdır

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

Ama:: Ayrıca, openquery ile size ekin için bu sözdizimini, daha doğru, kullanabilirsiniz

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

Ve evet, cümle sadece sütun bilgilerini değil, değerleri de ekleyecektir. yalnızca bir INSERT gerçekleştirmek için OPENQUERY kullandığınızda

+2

Sadece FYI: İkinci örnekte dört bölümlü adlandırma sözdizimi yalnızca Bağlantılı Sunucu türü Dağıtılmış İşlemlere kaydedilmişse çalışır. (Çoğu, sadece bir işarettir.) –

+0

İlk sorgunuzla, sütunları bir seçim yoluyla belirtmeden eklenecek sütunları nasıl belirliyorsunuz? – Abs

+0

Tam inserti sadece sütunları kimlik verileri veya varsayılan verilerle birlikte bırakıyorum (çoğu zaman varsayılan verileri de yazarım). Genellikle, tüm kayıt kümesini bir veri parçası olarak yazdığı gibi eklemek için daha hızlıdır. Açık sorgu, kodların yerleştirme düzeninde olduğunu varsayar (normal insert gibi). Doğru: ardışık olmayan cols'ları tercih etmeniz gerekiyorsa, seçmeyi kullanmanız gerekir, ancak performans – Zelloss

4

SELECT kayıtları kaydederse, INSERT etkilenen kayıt sayısı haricinde bir sonuç kümesi döndürmez. Bu SET NOCOUNT ON kullanılarak bastırılabilir; Ancak, bastırmaların görünürlük veya gerçekte gelen satır sayısı anlamına geleceğinden emin değilim. kayıtlar gelince

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

(1 row(s) affected) 

bir ÇIKIŞ maddesini kullanmak, INSERT gelen gerçekleşmesi için tek yolu, iade edilen. İstemci makinesinin OUTPUT INSERTED satırlarına erişimi olmayacak, böylece bunlar iade edilemez. aşağıdakileri çalıştırmayı denerseniz, bir hata alırsınız:

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

“INSERT” ifadesine başvurduğumda, gerçekten “OPENQUERY” içindeki SELECT sözcüğünden bahsediyorum. Bu sorgu, bağlantılı sunucu üzerinde yürütülür ve daha sonra yerel sunucuda "INSERT" yürütülür. Ancak, SQL server bir 'INSERT 'olduğunu ve dolayısıyla sonuç kümesini bağlı sunucudan döndürmediğini fark edecek mi? – Abs

+0

Ben sadece aynı ifadeleri koştum ve her iki ucunda profiler izledim. Sonuçlar, SELECT'in sadece OPENQUERY tarafından çağrılan sunucuda gerçekleştiğine ve SELECT'in insert için şablondan başka bir şeyden daha fazla bir şablon olarak hareket ettiğine inanmam için bana yol gösteriyor. – PseudoToad

1

yeterli olacaktır

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; 

lokal basit bir tablo çoğaltmak istiyorsanız

, bu SELECT ilk gerçekleştirir ve sonuçları atmak olacaktır. INSERT komutunun nasıl gönderileceğini belirlemek için sonuç kümesinden sütun meta verilerini kullanır. Bu nedenle, her zaman'un sonuna where 1=0'u eklemelisiniz.

SQL Server itibaren MySQL uygun sözdizimi:

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

MySQL tarafında genel sorgu kaydını etkinleştirmek Eğer bu komutlar SQL Server gelen görürsünüz:

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') 

Böylece seçimin iki kez gerçekleştirildiğini görebilirsiniz. where 1=0 olmadan, tüm satırlar MySQL sunucusu tarafından iade edilir.