2009-02-27 7 views
4

J'utilise Microsoft SQL Server 2005. J'ai besoin de synchroniser les données entre le serveur SQL et une base de données Oracle. La première chose dont j'ai besoin est de savoir si le nombre de données sur Oracle côté avec certains filtres (ici j'utilise ID comme un exemple simple). Le problème que j'ai est que la table sur le serveur ligné ou Oracle est très grande avec 4M lignes de données. La requête ci-dessus a pris environ 2 minutes pour récupérer les données. Ce code est juste une pièce simplifiée. En fait, mon SP a d'autres requêtes à mettre à jour, insérer des données du serveur ligné à mon serveur SQL. Le SP a pris des heures ou plus de 10 heures pour fonctionner avec une grande base de données Oracle. Par conséquent T-SQL avec le serveur ligné n'est pas bon pour moi.EXEC (requête) AT linkedServer avec Oracle DB

Récemment, j'ai trouvé OPENQUERY et EXEC (...) AT linedServer. OPENQUERY() est très rapide. Il a fallu environ 0 fois pour obtenir le même résultat. Cependant, il ne prend pas en charge les requêtes ou expressions variables. La requête doit être une chaîne constante littérale.

EXEC() est de la même manière qu'une requête directe vers Oracle. C'est rapide aussi. Par exemple:

EXEC ('SELECT COUNT(*) FROM owner.table1 WHERE id = ' + CAST(@id AS VARCHAR)) 
    AT oracleServer 

Le problème que j'ai est de savoir comment transmettre le résultat COUNT (*). J'ai essayé de google exemples dans le web et msdn. Tout ce que je peux trouver sont des exemples SQL ou ExpressSQL linedServer comme:

EXEC ('SELECT ? = COUNT(*) FROM ...', @myCount OUTPUT) AT expressSQL 

Cette requête ne fonctionne pas pour Oracle. Il semble dans Oracle, vous pouvez définir la valeur en sortie de cette manière:

SELECT COUNT(*) INTO myCount ... 

J'ai essayé ceci:

EXEC ('SELECT COUNT(*) INTO ? FROM ...', @myCount OUTPUT) AT oracleServer 
EXEC ('SELECT COUNT(*) INTO : FROM ...', @myCount OUTPUT) AT oracleServer 
EXEC ('SELECT : = COUNT(*) FROM ...', @myCount OUTPUT) AT oracleServer 

Aucun de ceux qui travaillent. J'ai reçu un message d'erreur disant que la requête n'est pas exécutable sur le serveur Oracle.

Je pourrais écrire un projet .Net SQL Server pour faire le travail. Avant cela, je me demande simplement s'il y a moyen de faire passer la valeur comme paramètre oupput pour que je mette les meilleurs codes T-SQL de performance dans mon SP?

Répondre

3

Juste une mise à jour rapide à ce sujet. Je pense que j'ai la solution. Je l'ai trouvé dans une discussion sur un problème similaire au Dev NewsGroup. Basé sur l'information, j'ai essayé ceci:

DECLARE @myCount int; 
DECLARE @sql nvarchar(max); 
set @sql = 
N'BEGIN 
    select count(*) into :myCount from DATAPARC.CTC_MANUAL_DATA; 
END;' 
EXEC (@sql, @myCount OUTPUT) AT oracleServer; 
PRINT @myCount; -- 3393065 

Wa! J'ai retrouvé le résultat en 3 secondes en comparant la requête T-SQL directement sur Orable DB (+ 2minutes). L'important est d'utiliser "BEGIN" et "END". pour envelopper la requête en tant que bloc anonyme et ne manquez pas ";" après END

Vous avez besoin d'un bloc anonyme pour les paramètres de sortie. Si vous n'avez que des entrées ou pas de paramètres, vous n'avez pas besoin du bloc et la requête fonctionne correctement.

Profitez-en! En passant, c'est une mise à jour rapide. Si vous ne me revoyez pas, je n'aurais aucun problème sur ce sujet.

+1

Récemment, je trouve une question intéressante avec cette méthode. J'ai posté des détails dans mon bog sur Using Exec() At Continued (http://davidchuprogramming.blogspot.com/2009/03/using-exec-at-continued.html). –

0

Avec les services liés le plus gros problème est la performance (à mon humble avis) [linkedserver]...[dbo.RemoteTable] vs OPENQUERY(linkedserver, 'Select * from dbo.RemoteTable')utilisent toujours la deuxième

Maintenant, pour répondre à la question. OPENQUERY et EXEC() AT est beaucoup plus rapide. EXEC(Select * from dbo.RemoteTable) AT linkedserver montrera les résultats, mais il n'y a aucun moyen de réutiliser.

Ma solution simple:

SELECT * INTO LocalTable FROM OPENQUERY(linkedserver, 'Select * from dbo.RemoteTable') 

OU

INSERT INTO LocalTable SELECT * FROM OPENQUERY(linkedserver, 'Select * from dbo.RemoteTable') 

beaucoup^10 plus rapide que

SELECT * INTO LocalTable FROM [linkedserver]...[dbo.RemoteTable]