Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Conseils d'utilisation de SQL Server avec Salesforce SOQL

Table des matières

  1. Présentation
  2. Les requêtes de sélection simples dans SQL Server ne fonctionnent pas
  3. Insertion groupée de données à l'aide du pilote SOQL
  4. Mettre à jour et supprimer le regroupement des requêtes
  5. Assistance transactionnelle Easysoft
  6. Validation de schéma paresseux
  7. Limites du fournisseur OLEDB pour ODBC de Microsoft

Aperçu

Ce document donne quelques conseils sur l'utilisation de SQL Server avec Salesforce. Les composants utilisés pour connecter SQL Server à Salesforce sont un serveur lié SQL Server et le pilote ODBC Easysoft Salesforce. La manière dont vous connectez SQL Server à Salesforce est décrite dans cet article. Pour les exemples de ce document, le nom du serveur lié (que vous référencez dans vos commandes SQL) utilisé est SFSOQL8.

Tout le SQL de ce document a été testé avec SQL Server 2017 et le pilote Easysoft Salesforce ODBC version 2.0.0.

Si vous souhaitez contribuer à ce document, veuillez envoyer votre soumission par e-mail à .

Les requêtes de sélection simples dans SQL Server ne fonctionnent pas

Supposons que vous essayez d'exécuter cette requête dans SQL Server :

SELECT Id FROM SFSOQL8...Account

SQL Server convertit ce SQL en :

SELECT "Tbl1002"."Id" "Col1004" FROM "Account" "Tbl1002"

Comme le langage SOQL de Salesforce ne prend pas en charge le renommage des tables et des colonnes de cette manière, vous vous retrouvez avec cette erreur :

OLE DB provider "MSDASQL" for linked server "SFSOQL8" returned message "[Easysoft][Salesforce SOQL ODBC Driver]General error: Query Failed: 'MALFORMED_QUERY: only aggregate expressions use field aliasing'". Msg 7320, Level 16, State 2, Line 1 Cannot execute the query "SELECT "Tbl1002"."Id" "Col1004" FROM "Account" "Tbl1002"" against OLE DB provider "MSDASQL" for linked server "SFSOQL8".

SQL Server propose deux méthodes pour envoyer SOQL au pilote Easysoft :

  1. OPENQUERY , qui peut être utilisé conjointement avec des tables locales pour joindre des données distantes et locales.
  2. EXEC qui peut être utilisé avec des paramètres pour exécuter directement votre SOQL sur Salesforce.

Pour illustrer ces méthodes, nous commencerons par une jointure de table SOQL :

SELECT Id, Amount, Name, ( SELECT Quantity, ListPrice, PricebookEntry.UnitPrice, PricebookEntry.Name FROM OpportunityLineItems ) FROM Opportunity

Dans SQL Server, vous pouvez exécuter l'une des requêtes suivantes :

SELECT * FROM OPENQUERY(SFSOQL8, 'SELECT Id, Amount, Name, ( SELECT Quantity, ListPrice, PricebookEntry.UnitPrice, PricebookEntry.Name FROM OpportunityLineItems ) FROM Opportunity')

—Ou—

EXEC ('SELECT Id, Amount, Name, ( SELECT Quantity, ListPrice, PricebookEntry.UnitPrice, PricebookEntry.Name FROM OpportunityLineItems ) FROM Opportunity') at SFSOQL8

Il n'y a presque aucune différence de performances car la SOQL que vous avez écrite est transmise directement au serveur Salesforce.

De même, toutes les fonctions SOQL sont également disponibles en utilisant les mêmes méthodes :

SELECT * FROM OPENQUERY(SFSOQL8, 'select Id, Name, DISTANCE(CustLocation__c , GEOLOCATION(37.775,-122.418), ''mi'') from Account where Name like ''Bur%'' ')
SELECT * FROM OPENQUERY(SFSOQL8, 'SELECT Type, BillingCountry, GROUPING(Type) grpType, GROUPING(BillingCountry) grpCty, COUNT(id) accts FROM Account GROUP BY CUBE(Type, BillingCountry) ORDER BY GROUPING(Type), GROUPING(BillingCountry)')

Si vous transmettez une SOQL non valide, le pilote Easysoft SOQL renverra l'erreur directement depuis Salesforce. Par exemple :

SELECT * FROM OPENQUERY(SFSOQL8, 'select Id, Name, DISTANCE(CustLocation__c , GEOLOCATION(37.775,-122.418), ''mo'') from Account where Name like ''Bur%'' ')
OLE DB provider "MSDASQL" for linked server "SFSOQL8" returned message "[Easysoft][Salesforce SOQL ODBC Driver]General error: Query Failed: 'INVALID_FIELD: 
select Id, Name, DISTANCE(CustLocation__c , GEOLOCATION(37.775
                          ^
ERROR at Row:1:Column:27
Invalid distance unit: mo. Valid unit: 'mi', 'km''".
Msg 7320, Level 16, State 2, Line 1
Cannot execute the query "select Id, Name, DISTANCE(CustLocation__c , GEOLOCATION(37.775,-122.418), 'mo') from Account where Name like 'Bur%' " against OLE DB provider "MSDASQL" for linked server "SFSOQL8". 

Vous trouverez plus d'informations sur le langage SOQL ici.

Insertion groupée de données à l'aide du pilote SOQL

Dans l'API SOAP de Salesforce, il existe une fonction qui vous permet d'insérer jusqu'à 200 lignes de données à partir d'un seul appel d'API SOAP. Le pilote Easysoft Salesforce SOQL ODBC utilise cette fonction et vous permet d'utiliser SQL Server TSQL pour charger en bloc jusqu'à 200 lignes à la fois.

Dans mon exemple, je vais ajouter de nouveaux enregistrements à l'objet Compte dans Salesforce. Ceci est un exemple très basique avec seulement quelques colonnes de données, mais j'espère que cela explique comment les insertions en bloc sont possibles à partir de SQL Server. Dans SQL Server, j'ai une table locale appelée Account qui ressemble à :

begin
    declare @BlockCount as int
    declare @IsPosted as int
    declare @PrmName As nvarchar(255)
    declare @PrmAddress As nvarchar(255)
    declare @PrmTown As nvarchar(40)
    declare @PrmPostCode As nvarchar(30)
    declare @PrmDescription As nvarchar(255)
	declare @SQL as nvarchar(255)

	set @BlockCount=0
	set @SQL='insert into Account (Name, BillingStreet, BillingCity, BillingPostalCode, Description ) values ( ?, ?, ?, ?, ? )'

	declare select_cursor cursor local FORWARD_ONLY for 
		select AccName, "Property Description", "Address", Town, PostCode from Account Order by Id

	open select_cursor
	fetch next from select_cursor into @PrmName, @PrmAddress, @PrmTown, @PrmPostCode, @PrmDescription
	while @@FETCH_STATUS=0
	begin
		if (@BlockCount=0)
		Begin
			set @IsPosted=0
			exec('Begin Trans') at SFSOQL8
		end
		set @BlockCount=@BlockCount+1

		exec (@SQL, @PrmName, @PrmAddress, @PrmTown, @PrmPostCode, @PrmDescription) at SFSOQL8

		if (@BlockCount=200)
		Begin
			set @IsPosted=1
			exec('Commit') at SFSOQL8
		end
		fetch next from select_cursor into @PrmName, @PrmAddress, @PrmTown, @PrmPostCode, @PrmDescription

	end

	if (@IsPosted=0)
	begin
		exec('Commit') at SFSOQL8
	end
	
	close select_cursor;
	deallocate select_cursor;
end

Ce TSQL fonctionne en lisant ma table de compte locale dans un curseur.

Au début du premier bloc de 200 lignes, le Begin Trans est appelé, ce qui indique au pilote Easysoft que toutes les données qui lui sont transmises seront conservées jusqu'à ce qu'un Commit ou un Rollback est appelé.

Le EXEC envoie chaque ligne présente dans le curseur au driver Easysoft. Le pilote crée ensuite l'appel d'API SOAP requis. Lorsque 200 lignes ont été envoyées à Easysoft, j'envoie un Commit , ce qui amène le pilote à envoyer l'appel d'API SOAP à Salesforce.

Lorsque la fin du curseur est atteinte, s'il y a des enregistrements envoyés au pilote Easysoft qui n'ont pas été passés à Salesforce, j'envoie un dernier Commit . Le curseur est alors fermé et désalloué.

La limite de 200 lignes est une limite interne dans Salesforce. Si vous essayez d'envoyer plus de 200 lignes, vous obtiendrez une erreur Salesforce. Le pilote Easysoft n'a pas de limites intégrées, donc si Salesforce augmente la limite de 200 lignes dans les futures versions de l'API SOAP, le pilote Easysoft fonctionnera automatiquement avec la nouvelle limite.

Lorsque vous utilisez cette méthode d'insertion en bloc, il n'y a pas de limite au nombre de tables dans lesquelles vous pouvez insérer des données dans un seul bloc, donc le TSQL suivant fonctionnera :

Begin
	exec('Begin Trans') at SFSOQL8
	exec('Insert into Account ( Name ) values (''Richard Test'') ') at SFSOQL8
	exec('Insert into Opportunity ( Name, StageName, CloseDate ) values (''Richard Test'', ''My Stage'', ''2018-08-14T10:07:00Z'') ') at SFSOQL8
	exec('Commit') at SFSOQL8
End

Lorsque vous utilisez la méthode Begin Trans/Commit pour les insertions, vous ne pouvez envoyer que des instructions d'insertion. Vous ne pouvez pas mélanger et faire correspondre les insertions et les mises à jour car cela n'est pas pris en charge dans l'API Salesforce SOAP.

Mettre à jour et supprimer le regroupement des requêtes

Notre pilote SOQL a une méthode intégrée pour regrouper les transactions de données, lorsqu'il est utilisé avec une requête UPDATE ou DELETE.

Cet exemple montre comment je mets à jour une colonne personnalisée avec une valeur définie.

EXEC ('UPDATE Account SET CustomerPriority__c=''low'' WHERE CustomerPriority__c=NULL') at SFSOQL8

Salesforce ne prend pas en charge les UPDATE ou les DELETE à l'aide de SOQL, le pilote Easysoft doit donc convertir la requête en SOQL SELECT. Les lignes renvoyées par le SELECT sont ensuite regroupées en blocs jusqu'à 200 et envoyées un bloc à la fois pour une mise à jour ou une suppression.

Assistance transactionnelle Easysoft

Le pilote ODBC Easysoft Salesforce SOQL ne prend en charge qu'un seul niveau de transaction. Donc un Begin Trans suivi de quelques INSERTs peuvent être envoyés à Salesforce avec un COMMIT ou jeté dans le pilote en utilisant un ROLLBACK .

Validation de schéma paresseux

Dans les propriétés de votre serveur lié SQL Server, la section "Options du serveur" contient une option pour "Lazy Schema Validation". Par défaut, cette valeur est définie sur FALSE, ce qui oblige SQL Server lors de l'exécution d'une instruction SELECT à envoyer l'instruction deux fois. La première fois qu'il est envoyé, SQL Server utilise les détails renvoyés pour créer les métadonnées sur votre jeu de résultats. Ensuite, la requête est à nouveau envoyée. C'est une surcharge assez coûteuse, donc Easysoft vous recommande de définir "Lazy Schema Validation" sur TRUE, ce qui signifie qu'un seul SELECT est envoyé, qui obtient à la fois les métadonnées et les données. Cela réduit également le nombre d'appels d'API Salesforce effectués.

Limitations du fournisseur OLEDB de Microsoft pour ODBC

Des détails sur les limitations du fournisseur OLEDB pour ODBC peuvent être trouvés ici :

https://msdn.microsoft.com/en-us/library/ms719628(v=vs.85).aspx