J'ai un processus qui saisit un tas d'enregistrements (1000) et les exploite, et lorsque j'ai terminé, je dois en marquer un grand nombre comme étant traités. Je peux l'indiquer avec une grande liste d'identifiants. J'essaie d'éviter le modèle de "mises à jour dans une boucle". J'aimerais donc trouver un moyen plus efficace d'envoyer ce sac d'ID dans un processus stocké MS SQL Server 2008.
Proposition n ° 1 - Paramètres valorisés de la table. Je peux définir un type de table avec seulement un champ ID et envoyer une table contenant des ID à mettre à jour.
Proposition n ° 2 - Paramètre XML (varchar) avec OPENXML () dans le corps de la procédure.
Proposition n ° 3 - Analyse de la liste. Je préférerais éviter cela, si possible, car cela semble difficile à manier et sujet aux erreurs.
Une préférence parmi celles-ci, ou des idées que j'ai manquées?
la source
Réponses:
Les meilleurs articles sur ce sujet sont par Erland Sommarskog:
Il couvre toutes les options et explique plutôt bien.
Désolé pour la brièveté de la réponse, mais l'article d'Erland sur Arrays est comme les livres de Joe Celko sur les arbres et autres friandises SQL :)
la source
Il existe une grande discussion à ce sujet sur StackOverflow qui couvre de nombreuses approches. Celui que je préfère pour SQL Server 2008+ consiste à utiliser des paramètres table . C’est essentiellement la solution de SQL Server à votre problème: transmettre une liste de valeurs à une procédure stockée.
Les avantages de cette approche sont les suivants:
Cependant, prenez note que si vous appelez une procédure stockée qui utilise des TVP via ADO.NET ou ODBC et regardez l'activité avec SQL Server Profiler, vous remarquerez que SQL Server reçoit plusieurs
INSERT
instructions pour charger la TVP, une pour chaque ligne. dans le TVP , suivi de l'appel de la procédure. C'est par conception . Ce lot deINSERT
s doit être compilé chaque fois que la procédure est appelée et constitue une petite surcharge. Cependant, même avec cette surcharge, TVPs encore soufflent loin d' autres approches en termes de performance et de facilité d' utilisation pour la majorité des cas d'utilisation.Si vous souhaitez en savoir plus, Erland Sommarskog comprend parfaitement le fonctionnement des paramètres de table et fournit plusieurs exemples.
Voici un autre exemple que j'ai concocté:
la source
CREATE TYPE
instruction au début a-t-elle fonctionné avec succès? Quelle version de SQL Server utilisez-vous?@customer_list
pas@param1
. L'exemple montre simplement que vous pouvez mélanger différents types de paramètres.L’ensemble du sujet est traité dans l’ article définitif d’Erland Sommarskog: "Tableaux et liste dans SQL Server" . Faites votre choix de la version à choisir.
Résumé, pour les versions antérieures à SQL Server 2008, où les TVP l'emportent sur le reste
L’article mérite quand même une lecture pour voir d’autres techniques et réflexions.
Edit: réponse tardive pour des listes énormes ailleurs: Passage de paramètres de tableau à une procédure stockée
la source
Je sais que je suis en retard pour ce parti, mais j’avais un problème de ce type dans le passé, obligé d’envoyer jusqu’à 100 000 gros chiffres et j’ai fait quelques points de repère. Nous avons fini par les envoyer au format binaire, sous forme d'image - plus rapide que tout le reste, jusqu'à 100 000 numéros.
Voici mon ancien code (SQL Server 2005):
Le code suivant contient des entiers dans un blob binaire. Je suis en train d'inverser l'ordre des octets ici:
la source
Je suis déchirée entre vous parler de SO et répondre ici, car c'est presque une question de programmation. Mais comme j'ai déjà une solution que j'utilise ... je vais poster ça;)
En procédant ainsi, vous introduisez une chaîne délimitée par des virgules (simple scission, mais pas de scission de style CSV) dans la procédure stockée sous forme de varchar (4000), puis vous insérez cette liste dans cette fonction et récupérez une table pratique, une table de varchars seulement.
Cela vous permet d’envoyer les valeurs des identifiants que vous souhaitez traiter et vous pouvez effectuer une jointure simple à ce stade.
Alternativement, vous pouvez faire quelque chose avec un CLR DataTable et l'introduire, mais cela prend un peu plus de temps pour supporter et tout le monde comprend les listes CSV.
la source
Je reçois régulièrement des ensembles de 1 000 lignes et de 10 000 lignes envoyées à partir de notre application pour être traitées par diverses procédures stockées SQL Server.
Pour répondre aux exigences de performances, nous utilisons des programmes de partenariat, mais vous devez implémenter votre propre résumé de dbDataReader pour résoudre certains problèmes de performances dans son mode de traitement par défaut. Je n'entrerai pas dans les tenants et aboutissants car ils sont hors de portée pour cette demande.
Je n'ai pas envisagé le traitement XML car je n'ai pas trouvé d'implémentation XML qui reste performante avec plus de 10 000 "lignes".
Le traitement de liste peut être traité par un traitement de table de décompte (nombres) à une dimension et à deux dimensions. Nous les avons utilisées avec succès dans divers domaines, mais les points de contrôle tactiles bien gérés sont plus performants quand il existe plus de deux cents "lignes".
Comme pour tous les choix concernant le traitement SQL Server, vous devez faire votre choix en fonction du modèle d'utilisation.
la source
J'ai enfin eu la chance de faire quelques TableValuedParameters et ils fonctionnent très bien, alors je vais coller un code complet qui montre comment je les utilise, avec un échantillon de mon code actuel: (note: nous utilisons ADO .NET)
Remarque: j'écris du code pour un service, et j'ai beaucoup de bits de code prédéfinis dans l'autre classe, mais j'écris ceci en tant qu'application console afin que je puisse le déboguer, alors j'ai tout extrait de l'application de la console. Excusez mon style de codage (comme les chaînes de connexion codées en dur) car il s’agissait en quelque sorte de "construire celui à jeter". Je voulais montrer comment utiliser un
List<customObject>
et l'insérer facilement dans la base de données sous forme de tableau, que je peux utiliser dans la procédure stockée. C # et TSQL code ci-dessous:Aussi, je vais prendre des critiques constructives sur mon style de codage si vous avez cela à offrir (à tous les lecteurs qui rencontrent cette question) mais s'il vous plaît gardez-le constructif;) ... Si vous voulez vraiment de moi, retrouvez-moi dans le forum de discussion ici . Espérons que, avec ce morceau de code, on peut voir comment ils peuvent utiliser le code
List<Current>
que je définis comme une table dans la base de données et unList<T>
dans leur application.la source
Je voudrais soit aller avec la proposition n ° 1 ou, au lieu de cela, créer une table de travail qui ne contient que les identifiants traités. Insérez dans cette table pendant le traitement, puis une fois terminé, appelez un proc similaire à celui-ci:
Vous ferez beaucoup d'inserts, mais ils seront sur une petite table, donc ça devrait être rapide. Vous pouvez également grouper vos insertions en utilisant ADO.net ou l’adaptateur de données que vous utilisez.
la source
Le titre de la question inclut la tâche permettant de transmettre les données d'une application dans la procédure stockée. Cette partie est exclue par le corps de la question, mais permettez-moi de répondre également à cette question.
Dans le contexte de sql-server-2008, tel que spécifié par les balises, il existe un autre excellent article de E. Sommarskog Arrays and Lists dans SQL Server 2008 . BTW je l'ai trouvé dans l'article Marian cité dans sa réponse.
Au lieu de simplement donner le lien, je cite sa liste de contenu:
Au-delà des techniques mentionnées ici, j’ai le sentiment que, dans certains cas, la copie en bloc et l’insert en masse méritent d’être mentionnés dans les grandes lignes.
la source
Pour MS SQL 2016 dernière version
Avec MS SQL 2016, ils introduisent une nouvelle fonction: SPLIT_STRING () pour analyser plusieurs valeurs.
Cela peut résoudre votre problème facilement.
Pour MS SQL Ancienne Version
Si vous utilisez une version plus ancienne, suivez cette étape:
D'abord créer une fonction:
Après avoir créé ceci, passez votre chaîne à cette fonction avec separator.
J'espère que cela vous aide. :-)
la source
Utilisez-le pour créer "create type table". exemple simple pour l'utilisateur
la source