ADBLOCK DEAKTIVIEREN

ADBlock blockiert einige Inhalte auf der Website

ADBlock errore
Gefundene Ergebnisse: 

Frage

Ich habe eine Datenbanktabelle und eines der Felder (nicht der Primärschlüssel) einen eindeutigen Index für es ist. Jetzt möchte ich Werte in dieser Spalte für zwei Reihen tauschen. Wie kann dies geschehen? Zwei Hacks ich kenne, sind:

  1. die beiden Zeilen löschen und legen Sie sie wieder.
  2. Update Zeilen mit einem anderen Wert und Swap und dann aktualisieren, um tatsächlichen Wert.

Aber ich will nicht für diese gehen, da sie die geeignete Lösung für das Problem nicht zu sein scheinen. Könnte jemand mir helfen?

Lösung

Ich glaube, Sie für Lösung gehen sollten 2. Es gibt keine ‚Swap‘ -Funktion in einer SQL-Variante ich kenne.

Wenn Sie dies regelmäßig tun müssen, schlage ich Lösung 1, je nachdem, wie andere Teile der Software diese Daten verwenden. Sie können Sperren Probleme haben, wenn Sie nicht vorsichtig sind.

Aber kurz:. Es gibt keine andere Lösung als die, die Sie zur Verfügung gestellt

Wenn Sie möchten, hinterlassen Sie uns Ihre Meinung

War der Artikel hilfreich und ist er richtig übersetzt?

ANDERE TIPPS

Das Zauberwort ist DEFERRABLE hier:

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;

ERGEBNIS:

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)

Weitere Andy Irving Antwort

für mich gearbeitet (auf SQL Server 2005) in einer ähnlichen Situation wo ich einen zusammengesetzten Schlüssel und ich brauche ein Feld zu tauschen, den Teil der eindeutigen Einschränkung ist.

-Taste: pID, LNUM rec1: 10, 0 REC2: 10, 1 REC3: 10, 2

und ich brauche LNUM zu tauschen, so dass das Ergebnis

-Taste: pID, LNUM REC1: 10, 1 REC2: 10, 2 REC3: 10, 0

die SQL benötigt:

UPDATE    DOCDATA    
SET       LNUM = CASE LNUM
              WHEN 0 THEN 1
              WHEN 1 THEN 2 
              WHEN 2 THEN 0 
          END
WHERE     (pID = 10) 
  AND     (LNUM IN (0, 1, 2))

Es ist ein weiterer Ansatz, die mit SQL Server funktionieren: Verwenden Sie eine temporäre Tabelle, um es in Ihrer UPDATE-Anweisung beitreten

.

Das Problem wird durch zwei Reihen mit dem gleichen Wert zur gleichen Zeit verursacht wird, , aber wenn Sie beiden Zeilen auf einmal aktualisieren (um ihre neue, einzigartigen Werte), gibt es keine Beschränkung verletzt.

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)

Dank Rich-H für diese Technik. - Mark

Ich denke auch, dass # 2 ist die beste Wette, obwohl ich sicher sein, wäre es im Rahmen einer Transaktion, falls etwas schief geht zu wickeln Mitte zu aktualisieren.

Eine Alternative (da Sie danach gefragt werden) würde die eindeutige Index-Werte mit unterschiedlichen Werten zu aktualisieren sein, alle anderen Werte in den Reihen diejenigen der anderen Zeile zu aktualisieren. Dadurch bedeutet, dass Sie die eindeutigen Index-Werte allein lassen können, und am Ende, am Ende mit den Daten, die Sie wollen. Seien Sie vorsichtig, falls einige andere Tabellenverweise in dieser Tabelle in einer Fremdschlüsselbeziehung, dass alle Beziehungen in der DB erhalten bleiben.

Ich habe das gleiche Problem. Hier ist meine vorgeschlagene Ansatz in PostgreSQL. In meinem Fall mein eindeutiger Index ist ein Sequenzwert, eine explizite Benutzer Ordnung auf meinen Zeilen zu definieren. Der Benutzer wird Reihen mische um in einem web-app, dann die Änderungen vor.

Ich plane einen „vor“ Trigger hinzuzufügen. In diesem Trigger, wenn mein einzigartiger Indexwert aktualisiert wird, werde ich schauen, um zu sehen, ob irgendeine andere Zeile bereits meinen neuen Wert hält. Wenn ja, ich gebe ihnen meinen alten Wert und effektiv den Wert aus ihnen stehlen.

Ich hoffe, dass PostgreSQL erlaubt mir diese shuffle in dem vor-Trigger zu tun.

ich Post zurück und lassen Sie meine Meilen kennen.

Sie kennen die PK der beiden Reihen Angenommen, Sie aktualisieren möchten ... Das funktioniert in SQL Server, kann nicht für andere Produkte sprechen. SQL ist (sein soll) Atom auf Anweisungsebene:

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;

, so dass Sie gehen aus:

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

zu:

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

Für Oracle gibt es eine Option, ABGEGRENZTE, aber Sie haben es zu einem Zwang hinzuzufügen.

SET CONSTRAINT emp_no_fk_par DEFERRED; 

Für alle Einschränkungen zu verschieben, die während der gesamten Sitzung deferrable sind, können Sie die ALTE SESSION SET Constraints = ABGEGRENZTE Anweisung verwenden.

Quelle

Oracle hat die Integritätsprüfung verschoben, die genau diese lösen, aber es ist in SQL Server oder MySQL nicht verfügbar.

In SQL Server kann die MERGE-Anweisung Zeilen aktualisieren, die normalerweise einen eindeutigen Schlüssel / INDEX brechen. (Just getestet, weil ich war neugierig.)

Allerdings würden Sie eine temporäre Tabelle / Variable zu liefern MERGE w / die notwendigen Zeilen verwenden.

Ich denke, in der Regel von einem Wert, der absolut kein Index in meinem Tisch haben könnte. In der Regel - für eindeutige Spaltenwerte - es ist wirklich einfach. Zum Beispiel für Werte der Spalte ‚Position‘ (Informationen über die Reihenfolge mehrerer Elemente) es ist 0

Dann können Sie Wert A auf eine Variable kopieren, aktualisieren Sie es mit dem Wert B und dann von Ihrem variablen Sollwert B. Zwei Anfragen, ich kenne keine bessere Lösung though.

1) schalten die IDs für Name

id    student 

1     Abbot   
2     Doris  
3     Emerson 
4     Green  
5     Jeames  

Für den Probe-Eingang, der Ausgang ist:

id Schüler

1     Doris   
2     Abbot   
3     Green   
4     Emerson 
5     Jeames  

"für den Fall n Anzahl der Zeilen, wie es schafft ......"

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow