2009-02-11 21 views
15

ho una query di selezione che fa un po 'di manipolazione del testo riformattare essenzialmente un campo in modo che io possa cercarlo in un altro tavolo:SQL UPDATE guai in MS Access - l'operazione è necessaria una query aggiornabile

Se la mia prima tavola se ho un campo come "J1/2" cerca l'ID di un record in una tabella diversa con J1 e J2 nei campi appropriati.

Questo funziona tutto bene.

Ora voglio aggiornare la tabella originale, quindi non c'è bisogno di fare ricerche utilizzando più questo manipolazione delle stringhe, ma i miei tentativi di query di aggiornamento terminare con "l'operazione è necessaria una query aggiornabile"

Tutte le idee?

mio SELECT:

SELECT DISTINCT 
t1.DD, 
t1.TN, 
t1.DD & " J" & MID(t1.TN,2,1) AS CalculatedStart, 
t1.DD & " J" & MID(t1.TN,4,1) AS CalculatedEnd, 
t2.ID 
FROM t1 INNER JOIN t2 
ON (t1.DD & " J" & MID(t1.TN,2,1)=t2.StartLink) 
AND (t1.DD & " J" & MID(t1.TN,4,1)=t2.EndLink) 
WHERE t1.TN Like "J?/?" 
AND t1.DD Like "M*"; 

Recall - questo funziona bene e ho la necessaria t2.ID fuori dall'altra parte.

quindi voglio fare qualcosa di simile:

UPDATE t1 SET t2ID = (
    SELECT Query1.ID 
    FROM Query1 
    WHERE t1.DD=Query1.DD 
    AND t1.TN=Query1.TN 
    ) 
WHERE t1.TN Like "J?/?" 
AND t1.DD Like "M*"; 

Solo questo fallisce. Questo è all'interno di MS Access stesso, quindi non riesco a immaginare un problema di autorizzazioni effettivo come la maggior parte dei problemi di "L'operazione deve utilizzare una query aggiornabile" sembra essere.

MODIFICA: cercare di semplificare il caso che non funziona.

Questa query UPDATE va bene:

UPDATE t1 
SET t2ID="Unknown" 
WHERE TN LIKE "J?/?" 
AND DD LIKE "M*"; 

Questo uno non riesce (Grazie Goedke - questo esempio non riesce ovviamente perché la sottoquery restituisce più di 1 risultato avevo semplificato per cercare di trovare il mio problema.)

UPDATE t1 
SET t2ID=(SELECT ID FROM t2) 
WHERE TN LIKE "J?/?" 
AND DD LIKE "M*"; 

Così ho sbagliato la sintassi della sottoquery in qualche modo?

EDIT: Questa istruzione SELECT è troppo bella:

SELECT t1.OA, t1.DD, t1.TN, t1.HATRIS, 
    query1.DD, query1.TN, query1.ID 
FROM t1 INNER JOIN query1 
ON t1.DD=query1.DD 
AND t1.TN=query1.TN 

Inoltre, utilizzando conteggio sul istruzione select sopra mostra che non v'è esattamente 1 ID viene restituito al (DD, TN) combinazione

EDIT :

Il caso più semplice che ho ottenuto ora - utilizzando varie istruzioni SELECT ora ho una tabella con solo 2 colonne: la chiave primaria di t1 e il valore che voglio inserire in t1.

io ancora non riesco a scrivere

UPDATE t1 SET t1.f2 = (SELECT t2.f2 FROM t2 WHERE t2.f1 = t1.f1) 

dove la chiave primaria del t1 è f1. Anche l'aggiunta di WHERE t1.f1 IN (SELECT f1 FROM t2) non aiuta. (Aggiunto per eliminare la possibilità che la sottoquery restituisca 0 risultati)

+0

Mi spiace per la modifica alla tua domanda: Ho premuto il pulsante di modifica sbagliato:/ – Godeke

+2

BTW, consiglio vivamente SQL Express come back end. Il motivo per cui non ho riscontrato questo problema è che utilizzo sempre un motore SQL sul back-end, non importa quanto piccolo sia il progetto ... Access SQL è apparentemente rotto in questo caso. – Godeke

+1

Jet SQL non è stato interrotto. Jet SQL ha più opzioni per rendere le query aggiornabili rispetto allo standard SQL92. Il mio suggerimento è di provare il predicato DISTINCTROW specifico per Jet. Può spesso forzare una query non aggiornabile per essere aggiornabile. –

risposta

6

Una sottoquery di (SELECT ID FROM t2) non può funzionare a meno che non vi sia un solo record in t2. Quale ID ti aspetti di usare?

Il messaggio di errore che viene segnalato normalmente si verifica quando si hanno join e non si includono tutte le chiavi primarie necessarie per l'aggiornamento alle tabelle in un modulo associato ai dati (ad esempio, il DISTINCT originale distrugge le informazioni sulle chiavi, quindi se fosse associato a un modulo, il modulo non sarebbe in grado di salvare nuovamente).

Il fatto che si stia utilizzando DISTINCT mi renderebbe sospetto che la query secondaria restituisca più di una riga nell'esempio più complesso. Questo è probabilmente il problema più comune con l'assegnazione di un risultato di una subquery: under-constraining the where clausola.

Un altro problema che ho riscontrato con l'assegnazione di una sottoquery è la sintassi della query interna non corretta. Almeno con i back-end SQL 2000 e 2005, il processore di query sarà silenziosamente in errore e restituirà NULL in questi casi. (Questo è, per quanto posso dire, un bug: non vedo alcuna ragione per cui qualcosa che restituirà un errore al livello più alto sarebbe permesso in silenzio in una subquery ... ma eccolo.)

EDIT : solo per garantire che né Paolo o non stavo andando pazzesco, ho creato le seguenti tabelle:

t1 | ID, FK, Data 
t2 | ID2, Data2 

ho fatto non mettere alcun vincolo tranne una chiave primaria su ID e ID2. Tutti i campi erano di testo, che è diverso da quello che uso normalmente per gli ID, ma dovrebbe essere irrilevante.

t1:

ID FK Data 
Key1  Data1 
Key2  Data2 
Key3  Data3 

t2:

ID2 Data2 
Key1 DataA 
Key2 DataB 
Key3 DataC 

Una query della forma:

UPDATE t1 SET t1.FK = (select ID2 from t2 where t2.ID2 = t1.ID); 

non riuscita con lo stesso messaggio Paul ottenuto.

select *, (select ID2 from t2 where t2.ID2 = t1.ID) as foreign from t1, 

funziona come previsto, quindi sappiamo la sintassi subquery non è da biasimare.

UPDATE t1 SET t1.FK = 'Key1' 

funziona anche come previsto, quindi non abbiamo una destinazione corrotta o non aggiornabile.

Nota: se cambio il back-end del database da nativo a SQL 2005, l'aggiornamento funziona! Un po 'di googling intorno, e trovo accesso MVP suggerendo DLookUp per sostituire una sottoquery:

http://www.eggheadcafe.com/software/aspnet/31849054/update-with-subquerycomp.aspx

A quanto pare questo è un bug in Access SQL, uno che è evitato quando si utilizza uno SQL Express 2000 o superiore back-end . (I risultati di Google per "subquery di aggiornamento degli accessi" supportano questa teoria).

Vedi qui per sapere come utilizzare questa soluzione: http://www.techonthenet.com/access/functions/domain/dlookup.php

+0

Buon punto: ho semplificato eccessivamente ... –

+0

Sei sicuro che le query meno semplificate restituiscano risultati singoli? – Godeke

+0

Lo sto verificando - avendo detto che la query originale dovrebbe restituire un singolo risultato. –

0

Per questo: UPDATE t1 SET t1.f2 = (SELECT T2.F2 da T2 DOVE t2.f1 = t1.f1)

UPDATE t1 INNER JOIN t2 ON t1.f1 = t2.f1 SET t1.f2 = [t2].[f2]; 
+0

No, ancora ottenere "L'operazione deve utilizzare una query aggiornabile" –

+0

FWIW Ho risolto il problema copiando "t2" che era in realtà una query, in una tabella temporanea, assegnando a quella tabella temporanea una chiave primaria su f1 (la colonna di join) –

6

ho havent't letto tutto il thread, ma questa è la soluzione che sto usando:

update (select * from t1 inner join t2 on t1.key = t2.key) set t1.field1 = t2.field2 

e che funziona bene in MS Access per me.

17

Devo valutare il commento di David W. Fenton sull'OP.

Questo è un problema molto fastidioso con Jet/ACE. Ma provare uno:

  1. andare alle proprietà della query (clicca sullo sfondo del riquadro in cui vengono visualizzati i tabelle) e impostare 'Unique Records 'Sì'
  2. Opzione 1 è l'equivalente di aggiungendo il po 'strano guardando DISTINCTROW parola chiave per la clausola SELECT, ad esempio

:

0.123.
UPDATE DISTINCTROW tblClient 
     INNER JOIN qryICMSClientCMFinite 
      ON tblClient.ClientID = qryICMSClientCMFinite.ClientID 
    SET tblClient.ClientCMType = "F"; 

Questo risolve così tanti problemi che coinvolgono questo messaggio di errore che è quasi ridicolo.

Ecco in breve MS Access: se non si conosce la soluzione alternativa per il problema del segreto commerciale, è possibile impiegare giorni a cercare la risposta. Per conoscere i 10.000 soluzioni alternative IS per programmare Access. È abbastanza di un avvertimento per chi non lo sapesse?

Ben

+0

+1 solo per l'avvertimento per chi non lo sapesse. Quello è oro. –

+0

Credo che Jet 3.x fosse più indulgente per l'aggiornabilità, ma in modi che non erano sincronizzati con altre implementazioni SQL. Penso che le modifiche all'aggiornamento di Jet 4 (che ci infastidivano da parte degli sviluppatori di Access con esperienza) fossero in realtà un passo nella direzione di rendere Jet SQL meno strano, anche se ha ancora alcune cose che non si comportano come gli altri SQL i dialetti fanno –

+0

E, BTW: In Access 2, l'impostazione predefinita per le query SELECT era DISTINCTROW invece di solo SELECT. Posso sempre dire quando incontro un'app con SELECT DISTINCTROW in tutto il luogo che è probabile che sia stata creata già in Access 2. –

7

Questo ha funzionato per me (accesso 2000)

UPDATE DISTINCTROW T1 inner join T2 on T2.f1 = T1.f1 SET f2 = f2; 
+1

Anche questo ha funzionato bene per me (Access 2010). Molte grazie. –

1

La mia soluzione era quella di cambiare la mia SQL su quel modo.

update (select o.pricein, g.pricein from operations o left join goods g on g.id = o.goodid where o.opertype = 4 and o.acct = 1) 
    set o.pricein = g.pricein 
+0

Stai dicendo che SQL è stato eseguito da Jet/ACE? Sono sorpreso, visto che mi sembra che manchi il tavolo dopo UPDATE.E se un aggiornamento funziona con un JOIN nel SELECT dipende interamente da quali tabelle si sta unendo e dagli indici nei campi uniti. –

1

Ho avuto lo stesso errore ("l'operazione è necessaria una query aggiornabile") utilizzando Access 2010 e mi è stata l'esecuzione di una semplice query di aggiornamento con un inner join. Tutto ciò che ho fatto è stato aggiungere una chiave primaria al tavolo a cui stavo partecipando (ne avevo già una, ovviamente, sul tavolo che stavo aggiornando) e tutto ha funzionato.