8
votes

T-sql isnumeric () et linq-to-sql

J'ai besoin de trouver la valeur la plus élevée de la base de données qui répond à une certaine convention de formatage. Plus précisément, je voudrais trouver la valeur la plus élevée qui ressemble à

eu999999 ('9' étant n'importe quel chiffre)

Sélectionnez Max (Col) retournera quelque chose comme "Euz ...", par exemple que je veux exclure. La requête suivante fait l'affaire, mais je ne peux pas produire ceci via Linq-to-SQL. Il semble n'y avoir aucune traduction de la fonction isnumeric () dans SQL Server. xxx

écrire une fonction de base de données, une procédure stockée ou autre chose de cette nature est loin de la liste. de mes solutions préférées, car cette table est au cœur de mon application et je ne peux pas facilement remplacer l'objet de la table avec autre chose.

Quelle est la meilleure solution?


0 commentaires

4 Réponses :


13
votes

Bien que isnumeric est manquant, vous pouvez toujours essayer le quasi équivalent pas comme '% [^ 0-9]% , c.-à-d. Il n'y a pas de non chiffre dans la chaîne, ou alternativement, la chaîne est vide ou consiste uniquement à des chiffres: xxx

Bien sûr, si vous savez que le nombre de chiffres est corrigé, cela peut être simplifié à xxx


3 commentaires

J'aime votre suggestion et je l'accepterai, mais mon préfixe (et la longueur) n'est pas une constante, malheureusement, je devrais donc générer l'expression de manière dynamique. Que je n'aime pas, et je pense aux moyens de changer le schéma afin que je puisse travailler autour de cela.


L'un des avantages de l'utilisation d'un comme sans fauve sauvage à l'avant est que cela est très index convivial (une vérification de la plage contre l'indice peut être effectuée).


Une alternative très intelligente à Isnumérique sur des expressions de longueur variable. Recherchez un caractère non numérique n'importe où dans la chaîne. Merci pour le conseil!



1
votes

Comme vous l'avez dit, il n'y a pas de traduction pour isnumeric de Linq à SQL. Il y a quelques options, vous avez déjà écrit la fonction de base de données et la procédure stockée vers le bas. J'aime ajouter deux autres.

Option 1: Vous pouvez le faire en mélangeant LINQ vers SQL avec LINQ aux objets, mais lorsque vous avez une grande base de données, ne vous attendez pas à de grandes performances: P>

var cols = (from c in db.Table where c.StartsWith("EU") select c).ToList();
var stripped = from c in cols select int.Parse(c.Replace("EU", ""));
var max = stripped.Max();


1 commentaires

Néanmoins, +1 pour la suggestion de changer mon schéma.



11
votes

Vous pouvez utiliser la fonction iSnumeric en ajoutant une méthode à une classe partielle pour le DataContext. Il serait similaire à l'utilisation d'un UDF.

dans la classe partielle de votre DataContext Ajoutez ceci: xxx

alors votre code l'utiliserait de cette manière: < Pré> xxx

ou vous pouvez utiliser max: xxx

en fonction de votre objectif final, il pourrait être possible de s'arrêter au max < / Code> variable et la prépendez avec le texte "UE" pour éviter la deuxième requête qui obtient le nom de la colonne.

EDIT: Comme mentionné dans les commentaires, la lacune de ceci approche est que la commande est effectuée sur le texte plutôt que sur des valeurs numériques et il n'y a actuellement aucune traduction de int32.parse sur sql.


4 commentaires

+1. Je suis assez étonné c'est possible. N'oubliez pas la commande ecatution par ordrebydescendants (p => p.replacédtext) est basée sur le texte (remplacementText est une chaîne / varchar), cela pourrait donc ne pas donner le résultat approprié. Il doit être jeté à un entier avant de tri.


@Steven merci, c'est une solution de contournement soignée pour des fonctions simples. Vous avez raison sur la commande. Malheureusement, il n'y a pas de solution de contournement pour cela et int32.parse n'a aucune traduction à SQL, donc pour le tri numérique Un vrai UDF / SPROC est le meilleur.


Même ici, c'est l'une des choses les plus slickest que j'ai vues depuis un moment.


Petite courte renonciation est que si vous utilisez Convert.Toint32, il est toujours évalué. Vous pouvez vous contourner ceci: (db.isnumeric (p.addressposcode) == 1? (Int?) Convert.toint32 (P.Addressposcode): null) <= SearchPostCode)



0
votes

Ma suggestion est de revenir à SQL en ligne et d'utiliser la méthode DataContext.Executequery (). Vous utiliseriez la requête SQL que vous avez postée au début.

C'est ce que j'ai fait dans des situations similaires. Non Idéal, accordé, en raison de l'absence de vérification de type et d'erreurs de syntaxe possibles, mais assurez-vous simplement qu'il est inclus dans les tests d'unités. Toutes les requêtes éventuelles ne sont pas couvertes par la syntaxe Linq, d'où l'existence d'exécuteur en premier lieu.


0 commentaires