Question Espaces réservés étendus pour SQL, par exemple O id ID IN (??)


Mise à jour de la prime: Déjà une très bonne réponse de Mark. Adapté: = dans:, ci-dessous. Cependant, je recherche toujours des schémas similaires en dehors de DBIx. Je suis juste intéressé à être compatible avec n'importe quoi.


J'ai besoin de conseils sur la syntaxe que j'ai choisie pour les espaces réservés "étendus" dans les instructions SQL paramétrées. Parce que la construction de certaines constructions (clauses IN) me gênait, j’ai choisi quelques raccourcis de syntaxe qui s’étendent automatiquement à l’ordinaire? placeholders.
Je les aime. Mais je veux l’emballer pour la distribution et je me demande s’ils sont facilement compréhensibles.

Fondamentalement, mes nouveaux espaces réservés sont ?? et :? (paramètres énumérés) et :& et :, et :| et :: (pour les espaces réservés nommés) avec les cas d'utilisation suivants:

-> db("  SELECT * FROM all WHERE id IN (??)  ", [$a, $b, $c, $d, $e])

le ?? se développe dans ?,?,?,?,?,... en fonction du nombre de $ args à mon db () func. Celui-ci est assez clair et sa syntaxe est en quelque sorte standardisée. Perls DBIx :: Simple l'utilise aussi. Donc, je suis certain que c'est une idée acceptable.

-> db("  SELECT :? FROM any WHERE id>0   ",  ["title", "frog", "id"]);
// Note: not actually parameterized attr, needs cleanup regex

Admet le. J'ai juste aimé le smiley. Fondamentalement cela :? placeholder étend un $ associatif en noms de colonne. Il jette toutes les valeurs $ args en fait. C'est en fait utile pour INSERT en conjonction avec ??, et parfois pour les clauses IN. Mais ici, je me demande déjà si cette nouvelle syntaxe est sensée, ou pas simplement un terme impropre car elle mélange: et? personnages. Mais de toute façon, il semble bien correspondre au schéma de syntaxe.

-> db("  UPDATE some SET :, WHERE :& AND (:|)   ", $row, $keys, $or);

Voici le mnémonique :, se développe dans une liste de name=:name paires séparées par , virgules. Tandis que le :& est une colonne =: liste de colonnes jointe par ANDs. Pour la parité, j'ai ajouté :|. Le: & a d'autres cas d'utilisation des commandes UPDATE, cependant.
Mais ma question ne concerne pas l'utilité, mais si:, et: & semblent être mémorables?

 -> db("  SELECT * FROM all WHERE name IN (::)  ", $assoc);

Après certains, j'ai aussi ajouté :: interpoler un :named,:value,:list très semblable à ?? se développe à ?,?,?. Cas d'utilisation similaires, et sensés pour l'uniformité.

De toute façon, quelqu'un d'autre a-t-il mis en place un tel système? Différents espaces réservés? Ou que recommanderiez-vous pour la simplicité? Mettre à jour: Je sais que l'interface OCI PHP Oracle peut également lier des paramètres de tableau, mais n'utilise pas d'espaces réservés spécifiques. Et je cherche des syntaxes de placeholder comparables.


10
2017-09-12 19:48


origine


Réponses:


Vous voudrez peut-être éviter d'utiliser := comme un espace réservé car il déjà a un usage dans par exemple MySQL.

Voir par exemple cette réponse pour un usage réel.


3
2017-09-12 20:01



J'aime l'idée de base de votre proposition, mais je n'aime pas la «dénomination» des espaces réservés. J'ai essentiellement deux objections:

  • Vos espaces réservés commencent soit par : ou avec ?. Vous devriez choisir un formulaire, un espace réservé peut être immédiatement reconnu. je choisirais ? car il y a moins de collisions possibles avec SQL et est plus courant pour désigner les espaces réservés.
  • Les espaces réservés sont difficiles à comprendre et difficiles à retenir. :& et :| me semble plausible, mais en distinguant ??, :?et : est assez difficile

J'ai changé ma Classe DB pour supporter plus de placeholders et être plus intelligent: DB_intelligent.php (la partie du fichier README concernant les espaces réservés ne s'applique pas à cette classe. Elle ne concerne que la classe normale.)

La classe DB possède deux types d’espaces réservés: le multifonctionnel ? espace réservé et l'espace réservé du tableau associatif ?x (x peut être ,, & ou |).

? espace réservé: Cet espace réservé détermine le type d'insertion à partir du type de l'argument:

null                => 'NULL'
'string'            => 'string'
array('foo', 'bar') => ('foo','bar')

?x espace réservé: Chaque élément du tableau est converti en un `field`='value' structure et implosé avec un délimiteur. Le délimiteur est spécifié par le x composant: , délimite par des virgules, & par AND et | par OR.

Exemple de code:

DB::x(
    'UPDATE table SET ?, WHERE value IN ? AND ?&',
    array('foo' => 'bar'),
    array('foo', 'bar'),
    array('hallo' => 'world', 'hi' => 'back')
);

// Results in this query:
// UPDATE table SET `foo`='bar' WHERE value IN ('foo','bar') AND `hallo`='world' AND `hi`='back'

Quelques réflexions sur la conception de cette version de la classe DB:

Une pensée évidente qui peut surgir: pourquoi ne pas utiliser ? pour tout types de données, même les tableaux associatifs. Ajouter seulement ?& et ?| aditionellement. En utilisant ? sur un tableau associatif serait identique à l'utilisation ?, dans le design actuel. La raison pour laquelle je ne l'ai pas fait est la sécurité. Vous voulez souvent insérer des données d'un <select multiple> dans la requête (IN ?). Mais comme HTML permet la mise en réseau (form[array]) les contrôles de formulaire peuvent également être soumis à un tableau associatif du même nom. Ainsi, mon compositeur de requêtes le reconnaîtrait comme un champ => liste de valeurs. Même si cela ne nuirait probablement pas à la sécurité, cela entraînerait une erreur SQL qui est mauvaise.


4
2017-09-27 14:33



Très propre! Je pense que les balises sont correctes tant que vous les documentez bien et fournissez de nombreux exemples lorsque vous les distribuez. C'est bien que tu aies inventé tes propres espaces réservés; quelqu'un devait penser à utiliser ?, après tout.


2
2017-09-12 19:53



Si vous êtes prêt à passer du temps pour apprendre doctrine alors vous pourriez faire des choses incroyables comme:

$q = Doctrine_Query::create()
    ->select('u.id')
    ->from('User u')
    ->whereIn('u.id', array(1, 3, 4, 5));

echo $q->getSqlQuery();

ce qui produirait une requête comme ça:

SELECT 
u.id AS u__id 
FROM user u 
WHERE u.id IN (?, 
?, 
?, 
?)

Cet exemple provient de:doctrine dql documentation


2
2017-10-01 11:51