Échanger des valeurs de colonne indexées uniques dans la base de données

J'ai une table de base de données et l'un des champs (pas la clé primaire) a un index unique dessus. Maintenant, je veux échanger des valeurs sous cette colonne pour deux lignes. Comment cela pourrait-il être fait? Deux hacks que je connais sont:

  1. Supprimez les deux lignes et réinsérez-les
  2. Mettre à jour les lignes avec une autre valeur et échangez puis mettez à jour à la valeur réelle.

Mais je ne veux pas y aller car ils ne semblent pas être la solution appropriée au problème. Quelqu'un pourrait m'aider?

0
ajouté édité
Vues: 9
Renommez les colonnes?
ajouté l'auteur MatBailie, source

19 Réponses

GDAL user-friendliness is basically nonexistent, but hot damn does it ever work well. I wrote up this guide to my own georeferencing experiments a few years ago: http://mike.teczno.com/notes/flea-market-mapping.html

C'est un peu démodé, mais les éléments de base sont là: trouvez les points correspondants entre votre image et une carte de référence (je recommande maintenant http://getlatlon. com en faveur de celui de http://gorissen.info ), utilisez gdal_translate pour assommer un raster virtuel, et puis vous ' re fondamentalement fait dans le sens que le fichier VRT résultant peut être converti en le GeoTIFF ou la tuile de votre choix.

I'm doing a lot with this right now, including collaborating with Tim Waters on the excellent server-side Map Warper mentioned in this thread, so there may be some new stuff in the near future loosely based on some experiments I did in JS last year: http://mike.teczno.com/notes/canvas-warp.html

22
ajouté
Michal, très cool merci! J'étais curieux de savoir comment trouver l'emplacement du pixel et vous mentionnez que vous avez utilisé la palette d'informations de Photoshop, ce qui est utile. Je pense que je peux m'en tirer avec une transformation de 1er ordre. Merci pour toutes ces informations!
ajouté l'auteur TiTi, source
QGIS 1.5 vient d'être publié et regarde le journal des changements ( qgis.org/ fr/component/content/article/108.html ) J'ai remarqué que "Inclusion du plugin d'outils Raster GDAL dans le noyau QGIS".
ajouté l'auteur TiTi, source

Je connais deux solutions Web qui méritent d'être examinées:

Je suis sûr que Tim Waters a ouvert son code, donc même si ces outils ne répondent pas à vos besoins, le fait de regarder leur source pourrait vous donner un aperçu.

Désolé, je ne peux pas poster plus d'un lien externe parce que je suis apparemment moins que de bonne réputation.

10
ajouté
vous devriez être en mesure d'ajouter plus de liens maintenant :)
ajouté l'auteur Greg, source
Fait intéressant, je regardais MapWarper l'autre jour. La source est sur GitHub: github.com/timwaters/mapwarper
ajouté l'auteur cynicalman, source

Je trouve le géoréférenceur de QGis assez décent pour un outil de pointage et clic. J'ai écrit un petit guide - géoréférencement d'images avec QGIS - qui est légèrement canadien - spécifique à la source, mais parcourt toutes les étapes nécessaires pour obtenir une carte arbitraire dans QGis.

7
ajouté

Je trouve le géoréférenceur de QGis assez décent pour un outil de pointage et clic. J'ai écrit un petit guide - géoréférencement d'images avec QGIS - qui est légèrement canadien - spécifique à la source, mais parcourt toutes les étapes nécessaires pour obtenir une carte arbitraire dans QGis.

7
ajouté

Vous pouvez également utiliser le plug-in Image rectifier dans MapWindow . Il utilise un algorithme amélioré à 4 ou 6 points.

2
ajouté

Vous pouvez également utiliser le plug-in Image rectifier dans MapWindow . Il utilise un algorithme amélioré à 4 ou 6 points.

2
ajouté

Puisque vous utilisez des images aériennes: avez-vous besoin d'orthorectification? Dans ce cas je pense que ILWIS serait votre meilleur pari, bien que GRASS le soutienne également (je n'ai pas essayé cela moi-même).

Le flux de travail pour ILWIS est décrit ici: http://spatial-analyst.net/PDF/TN_Ortofoto_in_ILWIS.pdf

2
ajouté
Le workflow d'orthorectification GRASS est disponible ici: grassbook.org -> Menu de gauche -> Exemple de chapitre: -> Antenne + Ortho (PDF)
ajouté l'auteur Dag Haavi Finstad, source

OpenEV est livré avec FWTools, cela me semble correct mais je charge facilement des images de 300 Mo dans QGIS et je les traite ici. Donc, je ne peux le recommander que d'un usage occasionnel.

http://OpenEV.sourceforge.net

Comprend NITF

et est construit avec GDAL

1
ajouté

Si vous avez ou pouvez créer un fichier * .geom pour votre image, vous pouvez utiliser orthoigen is gdal pour quorthorectify vos images.

1
ajouté

Je pense également que # 2 est le meilleur pari, même si je serais sûr de l'envelopper dans une transaction au cas où quelque chose se passe mal à mi-mise à jour.

Une alternative (puisque vous avez demandé) à mettre à jour les valeurs de l'index unique avec différentes valeurs serait de mettre à jour toutes les autres valeurs dans les lignes à celle de l'autre rangée. Cela signifie que vous pouvez laisser les valeurs de l'index unique et, à la fin, vous obtenez les données souhaitées. Attention toutefois, dans le cas où une autre table référence cette table dans une relation de clé étrangère, toutes les relations dans la BD restent intactes.

0
ajouté

Pour Oracle, il existe une option, DEFERRED, mais vous devez l'ajouter à votre contrainte.

SET CONSTRAINT emp_no_fk_par DEFERRED; 

Pour reporter TOUTES les contraintes reportables pendant toute la session, vous pouvez utiliser l'instruction ALTER SESSION SET constraints = DEFERRED.

Source

0
ajouté

Oracle a différé la vérification d'intégrité qui résout exactement cela, mais il n'est pas disponible dans SQL Server ou MySQL.

0
ajouté

Dans SQL Server, l'instruction MERGE peut mettre à jour des lignes qui normalement casseraient UNIQUE KEY / INDEX. (Juste testé cela parce que j'étais curieux.)

Cependant, vous devrez utiliser une table / variable temporaire pour fournir MERGE w / les lignes nécessaires.

0
ajouté

Le mot magique est DEFERRABLE ici:

DROP TABLE ztable CASCADE;
CREATE TABLE ztable
    ( id integer NOT NULL PRIMARY KEY
    , payload varchar
    );
INSERT INTO ztable(id,payload) VALUES (1,'one' ), (2,'two' ), (3,'three' );
SELECT * FROM ztable;


    -- This works, because there is no constraint
UPDATE ztable t1
SET payload=t2.payload
FROM ztable t2
WHERE t1.id IN (2,3)
AND t2.id IN (2,3)
AND t1.id <> t2.id
    ;
SELECT * FROM ztable;

ALTER TABLE ztable ADD CONSTRAINT OMG_WTF UNIQUE (payload)
    DEFERRABLE INITIALLY DEFERRED
    ;

    -- This should also work, because the constraint 
    -- is deferred until "commit time"
UPDATE ztable t1
SET payload=t2.payload
FROM ztable t2
WHERE t1.id IN (2,3)
AND t2.id IN (2,3)
AND t1.id <> t2.id
    ;
SELECT * FROM ztable;

RÉSULTAT:

DROP TABLE
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "ztable_pkey" for table "ztable"
CREATE TABLE
INSERT 0 3
 id | payload
----+---------
  1 | one
  2 | two
  3 | three
(3 rows)

UPDATE 2
 id | payload
----+---------
  1 | one
  2 | three
  3 | two
(3 rows)

NOTICE:  ALTER TABLE / ADD UNIQUE will create implicit index "omg_wtf" for table "ztable"
ALTER TABLE
UPDATE 2
 id | payload
----+---------
  1 | one
  2 | two
  3 | three
(3 rows)
0
ajouté
Est-ce que cela fonctionne dans MySQL?
ajouté l'auteur Marco Demaio, source
@MarcoDemaio je ne sais pas. Je crains que non: puisque MySQL n'autorise pas les mises à jour depuis les auto-jointures, je suppose qu'il fait des lectures incorrectes. Mais tu pourrais essayer ...
ajouté l'auteur wildplasser, source
propre, simple et fonctionne bien, merci l'homme :)
ajouté l'auteur Aldos, source

J'ai le même problème. Voici mon approche proposée dans PostgreSQL. Dans mon cas, mon index unique est une valeur de séquence, définissant un ordre d'utilisateur explicite sur mes lignes. L'utilisateur va mélanger les lignes dans une application Web, puis soumettre les modifications.

Je prévois d'ajouter un déclencheur "avant". Dans ce déclencheur, chaque fois que ma valeur d'index unique est mise à jour, je vais voir si une autre ligne contient déjà ma nouvelle valeur. Si c'est le cas, je leur donnerai mon ancienne valeur et je leur enlèverai effectivement la valeur.

J'espère que PostgreSQL me permettra de faire ce shuffle dans le trigger avant.

Je posterai et vous ferai connaître mon kilométrage.

0
ajouté

En supposant que vous connaissiez le PK des deux lignes que vous voulez mettre à jour ... Cela fonctionne dans SQL Server, ne peut pas parler pour d'autres produits. SQL est (supposé être) atomique au niveau de l'instruction:

CREATE TABLE testing
(
    cola int NOT NULL,
    colb CHAR(1) NOT NULL
);

CREATE UNIQUE INDEX UIX_testing_a ON testing(colb);

INSERT INTO testing VALUES (1, 'b');
INSERT INTO testing VALUES (2, 'a');

SELECT * FROM testing;

UPDATE testing
SET colb = CASE cola WHEN 1 THEN 'a'
                WHEN 2 THEN 'b'
                END
WHERE cola IN (1,2);

SELECT * FROM testing;

donc vous allez partir de:

cola    colb
------------
1       b
2       a

à:

cola    colb
------------
1       a
2       b
0
ajouté
Cela n'a pas fonctionné pour moi dans MySQL.
ajouté l'auteur activout.se, source

Je pense que vous devriez aller pour la solution 2. Il n'y a pas de fonction 'swap' dans toutes les variantes SQL que je connais.

Si vous devez le faire régulièrement, je suggère la solution 1, en fonction de la façon dont d'autres parties du logiciel utilisent ces données. Vous pouvez avoir des problèmes de verrouillage si vous ne faites pas attention.

Mais en un mot: il n'y a pas d'autre solution que celles que vous avez fournies.

0
ajouté

Il existe une autre approche qui fonctionne avec SQL Server: utilisez une jointure de table temporaire dans votre instruction UPDATE.

Le problème est dû au fait que deux lignes ont la même valeur en même temps , mais si vous mettez à jour les deux lignes à la fois (à leurs nouvelles valeurs uniques), il n'y a pas de violation de contrainte.

Pseudo-code:

-- setup initial data values:
insert into data_table(id, name) values(1, 'A')
insert into data_table(id, name) values(2, 'B')

-- create temp table that matches live table
select top 0 * into #tmp_data_table from data_table

-- insert records to be swapped
insert into #tmp_data_table(id, name) values(1, 'B')
insert into #tmp_data_table(id, name) values(2, 'A')

-- update both rows at once! No index violations!
update data_table set name = #tmp_data_table.name
from data_table join #tmp_data_table on (data_table.id = #tmp_data_table.id)

Merci à Rich H pour cette technique. - Marque

0
ajouté
Peut-être un peu vieux celui-là mais j'essayais de faire une page de 're-ordering' pour mon application Silverlight comme le client voulait trier leurs rapports par un ordre spécifique - j'ai ajouté une colonne de tri mais comme c'est une clé unique j'étais avoir du mal à le mettre à jour. J'ai fini par utiliser une variable de table mais le principe est le même (je n'aime pas beaucoup les tables temporaires pour être honnête!). Merci pour l'idée :)
ajouté l'auteur Charleh, source

Je pense généralement à une valeur qui n'a absolument aucun indice dans ma table pourrait avoir. Habituellement - pour des valeurs de colonnes uniques - c'est vraiment facile. Par exemple, pour les valeurs de la colonne 'position' (informations sur l'ordre de plusieurs éléments), c'est 0.

Vous pouvez ensuite copier la valeur A dans une variable, la mettre à jour avec la valeur B, puis définir la valeur B à partir de votre variable. Deux requêtes, je ne connais pas de meilleure solution.

0
ajouté