Buongiorno,
ringrazio gibra della collaborazione e ho capito che duplicavo la chiave primaria come da lui indicato.
La cosa strana è che dopo aver tolto la chiave primaria dalla SELECT la cosa non funzionasse correttamente. Mi dava gli stessi problemi di prima , pertanto ho sostituito dbs.execute con docmd.runsql, di seguito tutte le operazioni:

Dim dbs As Database
Dim x, y, z, k As DAO.Recordset
Dim p, c, q As Integer

Set dbs = CurrentDb
Set x = dbs.OpenRecordset("Contratti", dbOpenDynaset)
Set y = dbs.OpenRecordset("DClausole", dbOpenDynaset)
Set z = dbs.OpenRecordset("Prezzi", dbOpenDynaset)
Set k = dbs.OpenRecordset("Altro", dbOpenDynaset)

c = [Forms]![Clienti]![Contratto].[Form]![IDContratto]

' duplico il contratto selezionato

DoCmd.RunSQL "INSERT INTO Contratti " & "SELECT Contratti.DataInizio, Contratti.DataFine, Contratti.Cliente, Contratti.Confermato, Contratti.NoteContratto FROM Contratti " & " WHERE (((Contratti.IDContratto)=4))"



' definisco l'indice del nuovo contratto
x.MoveLast
p = x("IDContratto")

' duplico la parte relativa alle clausole

If y.EOF Or y.BOF Then GoTo s1 Else GoTo n1
n1:
y.MoveLast
q = y("IDDClausole")
DoCmd.RunSQL "INSERT INTO DClausole SELECT DClausole.DataDClausole, DClausole.Contratto, DClausole.Clausola, DClausole.[Val%], DClausole.Importo, DClausole.Condizione, DClausole.NoteCondizione, DClausole.Liquidazione, DClausole.Tipo, DClausole.Chiusa, DClausole.Applicabile" & " FROM DClausole " & "WHERE (((DClausole.Contratto)=" & c & "));"
dbs.Execute "UPDATE DClausole SET DClausole.Contratto =" & p & " WHERE (((DClausole.IDDClausole)>" & q & "));"

' duplico la parte relativa agli eventuali prezzi
s1:
If z.EOF Or z.BOF Then GoTo s2 Else GoTo n2
n2:
z.MoveLast
q = z("IDPrezzi")
DoCmd.RunSQL "INSERT INTO Prezzi SELECT Prezzi.Contratto, Prezzi.Articoli, Prezzi.Prezzo, Prezzi.Note FROM Prezzi WHERE (((Prezzi.Contratto)=" & c & "));"
dbs.Execute "UPDATE Prezzi SET Prezzi.Contratto = " & p & " WHERE (((Prezzi.IDPrezzi)>" & q & "));"

' duplico la parte relativa all'altro
s2:
If k.EOF Or k.BOF Then GoTo s3 Else GoTo n3
n3:
k.MoveLast
q = k("IDAltro")
DoCmd.RunSQL "INSERT INTO Altro SELECT Altro.DataAltro, Altro.Contratto, Altro.Descrizione, Altro.Quantità FROM Altro WHERE (((Altro.Contratto)=" & c & "));"
dbs.Execute "UPDATE Altro SET Altro.Contratto = " & p & " WHERE (((Altro.IDAltro) >" & q & "));"

s3:
Me.Contratti.Requery

Set x = Nothing
Set y = Nothing
Set z = Nothing
Set dbs = Nothing
Così facendo mi indicava tramite la finestra quali operazioni impedivano il successo della query.
Con grande stupore mi indicava che duplicavo ancora la chiave primaria cosa che in realtà non veniva fatta.
Dopo però aver lanciato l'SQL due volte, non mi dava più errore e funzionava correttamente.
Pertanto mia personalissima opinione, credo che con utilizzando database execute non mi abbia segnalato l'errore e scombinato qualcosa nelle tabelle, utilizzando docmd.runsql invece abbia bene o male rimesso a posto le cose.
Sostituendo dopo il DOCMD.RUNSQL con il DATABASE.EXECUTE, la query ritorna a funzionare senza le finestre che ti dicono quanti record vengono inseriti.
Ringrazio Gibra per l'aiuto fornito.
Alla prossima.
El Chorro