J'ai une table MySQL avec des coordonnées, les noms de colonne sont X et Y. Maintenant, je veux échanger les valeurs de colonne dans cette table, de sorte que X devienne Y et Y devienne X. La solution la plus apparente serait de renommer les colonnes, mais je Je ne veux pas faire de changements de structure car je n'ai pas nécessairement les autorisations pour le faire.
Est-ce possible de faire avec UPDATE d'une manière ou d'une autre? UPDATE table SET X = Y, Y = X ne fera évidemment pas ce que je veux.
Edit: Veuillez noter que ma restriction sur les autorisations, mentionnée ci-dessus, empêche efficacement l'utilisation d'ALTER TABLE ou d'autres commandes qui modifient la structure de la table / base de données. Renommer les colonnes ou en ajouter de nouvelles ne sont malheureusement pas des options.
UPDATE table SET X = Y, Y = X
c'est la manière standard de le faire en SQL, seul MySQL se comporte mal.Réponses:
J'ai juste eu à traiter de la même chose et je vais résumer mes conclusions.
L'
UPDATE table SET X=Y, Y=X
approche ne fonctionne évidemment pas, car elle définira simplement les deux valeurs sur Y.Voici une méthode qui utilise une variable temporaire. Merci à Antony pour les commentaires de http://beerpla.net/2009/02/17/swapping-column-values-in-mysql/ pour le tweak "IS NOT NULL". Sans cela, la requête fonctionne de manière imprévisible. Voir le schéma du tableau à la fin de l'article. Cette méthode n'échange pas les valeurs si l'une d'elles est NULL. Utilisez la méthode n ° 3 qui n'a pas cette limitation.
UPDATE swap_test SET x=y, y=@temp WHERE (@temp:=x) IS NOT NULL;
Cette méthode a été proposée par Dipin dans, encore une fois, les commentaires de http://beerpla.net/2009/02/17/swapping-column-values-in-mysql/ . Je pense que c'est la solution la plus élégante et la plus propre. Il fonctionne avec les valeurs NULL et non NULL.
UPDATE swap_test SET x=(@temp:=x), x = y, y = @temp;
Une autre approche que j'ai proposée et qui semble fonctionner:
UPDATE swap_test s1, swap_test s2 SET s1.x=s1.y, s1.y=s2.x WHERE s1.id=s2.id;
Essentiellement, la première table est celle qui est mise à jour et la deuxième est utilisée pour extraire les anciennes données.
Notez que cette approche nécessite la présence d'une clé primaire.
Voici mon schéma de test:
la source
Vous pouvez prendre la somme et soustraire la valeur opposée en utilisant X et Y
Voici un exemple de test (et cela fonctionne avec des nombres négatifs)
Voici le swap en cours
Essaie !!!
la source
TINYINT
ou d'énormes valeurs deINT
, vous avez raison !!!Le code suivant fonctionne pour tous les scénarios de mes tests rapides:
la source
UPDATE table swap_test
? Cela ne devrait-il pas être le casUPDATE swap_test
?UPDATE table SET X = Y, Y = X fera exactement ce que vous voulez (éditer: dans PostgreSQL, pas MySQL, voir ci-dessous). Les valeurs sont extraites de l'ancienne ligne et affectées à une nouvelle copie de la même ligne, puis l'ancienne ligne est remplacée. Vous n'avez pas besoin d'utiliser une table temporaire, une colonne temporaire ou d'autres astuces d'échange.
@ D4V360: Je vois. C'est choquant et inattendu. J'utilise PostgreSQL et ma réponse y fonctionne correctement (je l'ai essayé). Consultez la documentation de PostgreSQL UPDATE (sous Paramètres, expression), où elle mentionne que les expressions à droite des clauses SET utilisent explicitement les anciennes valeurs des colonnes. Je vois que les documents MySQL UPDATE correspondants contiennent la déclaration "Les affectations UPDATE à table unique sont généralement évaluées de gauche à droite", ce qui implique le comportement que vous décrivez.
Bon à savoir.
la source
Ok, donc juste pour le plaisir, tu peux faire ça! (en supposant que vous permutez les valeurs de chaîne)
Un peu de plaisir en abusant du processus d'évaluation de gauche à droite dans MySQL.
Sinon, utilisez simplement XOR s'il s'agit de nombres. Vous avez mentionné les coordonnées, alors avez-vous de jolies valeurs entières ou des chaînes complexes?
Edit: Le truc XOR fonctionne comme ça au fait:
la source
Je pense qu'avoir une variable d'échange intermédiaire est la meilleure pratique de cette manière:
Premièrement, cela fonctionne toujours; deuxièmement, cela fonctionne quel que soit le type de données.
Malgré les deux
et
fonctionnent généralement, uniquement pour le type de données numériques en passant, et il est de votre responsabilité d'éviter le débordement, vous ne pouvez pas utiliser XOR entre signé et non signé, vous ne pouvez pas non plus utiliser la somme pour la possibilité de débordement.
Et
ne fonctionne pas si c1 est 0 ou NULL ou une chaîne de longueur nulle ou juste des espaces.
Nous devons le changer pour
Voici les scripts:
la source
Deux alternatives 1. Utilisez une table temporaire 2. Examinez l' algorithme XOR
la source
Quelque chose comme ça?Edit: À propos du commentaire de Greg: Non, cela ne fonctionne pas:
la source
Cela fonctionne sûrement! J'en ai juste besoin pour échanger les colonnes de prix Euro et SKK. :)
Ce qui précède ne fonctionnera pas (ERREUR 1064 (42000): vous avez une erreur dans votre syntaxe SQL)
la source
En supposant que vous ayez des entiers signés dans vos colonnes, vous devrez peut-être utiliser CAST (a ^ b AS SIGNED), car le résultat de l'opérateur ^ est un entier 64 bits non signé dans MySQL.
Au cas où cela aiderait quelqu'un, voici la méthode que j'ai utilisée pour permuter la même colonne entre deux lignes données:
où $ 1 et $ 2 sont les clés de deux lignes et $ 3 est le résultat de la première requête.
la source
Je n'ai pas essayé mais
Pourrait le faire.
marque
la source
Vous pouvez changer les noms de colonne, mais c'est plus un hack. Mais méfiez-vous des index qui peuvent être sur ces colonnes
la source
Le nom de la table est client. les champs sont a et b, permutez une valeur à b ;.
UPDATE client SET a = (@ temp: = a), a = b, b = @temp
J'ai vérifié que cela fonctionnait bien.
la source
Dans SQL Server, vous pouvez utiliser cette requête:
la source
Échange de valeurs de colonne à l'aide d'une seule requête
METTRE À JOUR ma_table SET a = @ tmp: = a, a = b, b = @ tmp;
à votre santé...!
la source
Je devais simplement déplacer la valeur d'une colonne à l'autre (comme l'archivage) et réinitialiser la valeur de la colonne d'origine.
Le ci-dessous (référence de # 3 de la réponse acceptée ci-dessus) a fonctionné pour moi.
la source
la source
Cet exemple permute start_date et end_date pour les enregistrements où les dates sont dans le mauvais sens (lors de l'exécution d'ETL dans une réécriture majeure, j'ai trouvé des dates de début postérieures à leurs dates de fin . Down, mauvais programmeurs!).
In situ, j'utilise des MEDIUMINT pour des raisons de performances (comme les jours juliens, mais avec une racine 0 de 1900-01-01), donc j'étais d'accord pour faire une condition de WHERE mdu.start_date> mdu.end_date .
Les PK se trouvaient sur les 3 colonnes individuellement (pour des raisons opérationnelles / d'indexation).
la source
Supposons que vous souhaitiez échanger la valeur du prénom et du nom dans tb_user.
Le plus sûr serait:
la source
Vous pouvez postuler ci-dessous, cela a fonctionné parfaitement pour moi.
la source