9
votes

Ajouter des millisecondes à une date d'heure dans l'insertion TSQL dans

Je fais un insert dans la requête afin d'initialiser une nouvelle table. La clé primaire est RFQ_ID et Action_Time

Comment ajouter 1 milliseconde à chaque action_faction sur un nouvel enregistrement afin d'éviter une "violation de la contrainte principale" P>

INSERT INTO QSW_RFQ_Log
            (RFQ_ID, Action_Time, Quote_ID)
SELECT     RFQ_ID, GETDATE() AS Action_Time,  Quote_ID, 'Added to RFQ on Initialization' AS Note
FROM         QSW_Quote


0 commentaires

6 Réponses :


3
votes

Utilisez DADEADD , bien que de réaffecter votre question I Je ne suis pas totalement sûr que vous rencontrez ce problème si vous insérez des lignes simples à la fois (et, comme d'autres l'ont souligné, le vrai problème semble être votre PK):

DECLARE @datetime2 datetime2 = '2007-01-01 13:10:10.1111111'
SELECT '1 millisecond' ,DATEADD(millisecond,1,@datetime2)
UNION ALL
SELECT '2 milliseconds', DATEADD(millisecond,2,@datetime2)
UNION ALL
SELECT '1 microsecond', DATEADD(microsecond,1,@datetime2)
UNION ALL
SELECT '2 microseconds', DATEADD(microsecond,2,@datetime2)
UNION ALL
SELECT '49 nanoseconds', DATEADD(nanosecond,49,@datetime2)
UNION ALL
SELECT '50 nanoseconds', DATEADD(nanosecond,50,@datetime2)
UNION ALL
SELECT '150 nanoseconds', DATEADD(nanosecond,150,@datetime2);
/*
Returns:
1 millisecond     2007-01-01 13:10:10.1121111
2 milliseconds    2007-01-01 13:10:10.1131111
1 microsecond     2007-01-01 13:10:10.1111121
2 microseconds    2007-01-01 13:10:10.1111131
49 nanoseconds    2007-01-01 13:10:10.1111111
50 nanoseconds    2007-01-01 13:10:10.1111112
150 nanoseconds   2007-01-01 13:10:10.1111113
*/


1 commentaires

SQL Server 2008, il convient de noter que SQL Server 2008 (qui introduit DateTime2 + Nanosecond Arg)



1
votes

Comme suggéré ci-dessus, utilisez la fonction daaddd () , comme suit: xxx

tandis que l'instruction d'insertion de YR ne répertorie que trois champs à insérer, mais ont quatre valeurs Pour être inséré, il y a donc un autre problème là-bas ...


1 commentaires

Je fixe les "trois champs à insérer dans" l'erreur, il y a en fait une douzaine, mais je coupe cela pour la visibilité.



14
votes

Je pense que le vrai problème est que rfq_id, action_time ne doit pas être une clé primaire. Créez un clé de substitution principale et mettre un index non unique sur rfq_id, action_time .

update : Si vous voulez vraiment coller avec votre conception existante, vous pouvez faire ce que vous avez demandé, mais utiliser 10 millisecondes au lieu d'un milliseconde entre chaque rangée, pour compenser la faible précision de DateTime. Vous pouvez utiliser le numéro de ligne pour déterminer le nombre de millisecondes à ajouter afin d'obtenir un horodatage différent pour chaque ligne: xxx


1 commentaires

+1 - Ajout de commentaires supplémentaires sur d'autres gotchas à faire attention à une réponse, si cette approche ne peut pas être prise



10
votes

Je suis d'accord avec la réponse de Mark Byers comme une solution réelle. Je voulais juste ajouter un Gotcha, qu'avant SQL Server 2008, la précision DateTime est d'environ 333 ms. citation de MSDN :

Les valeurs DateTime sont arrondies à incréments de 0,000, .003, ou .007 Deuxièmement ...

Ajout de 1 ms aux dates ne résoudra pas votre problème.

par exemple par exemple xxx

Vous devez ajouter 3 ms chaque fois. Au mieux, cela fonctionnerait pour votre situation, mais tout simplement pas vraiment ce qui ressemble à une solution «propre», un peu de hack. Au pire, cela ne fonctionnerait tout simplement pas / échelle, en fonction des volumes de données / la densité de la propagation des données. Mais, vous devez être conscient de la précision DateTime Gotcha si vous vous dirigeez dans cet itinéraire.

SQL Server 2008 introduit DateTime2 qui a une précision de 100ns. Voir la réponse de Davek.


0 commentaires

2
votes

jamais entendu parler de "Robing Peter de payer Paul"?

Vous pouvez manipuler l'heure, qui est un vrai piratage, pour obtenir l'insert de travailler, mais qu'en est-il des inserts simultanés, ils auront des temps de chevauchement. Peut-être que cela ne se produira jamais sur la base de votre conception, mais j'ai appris au fil des ans pour ne jamais dire jamais.

C'est la raison exacte pour laquelle je ne fais jamais une date d'heure un pk, ils ne sont pas toujours uniques.

J'ai besoin de temps d'action comme clé primaire, période.

Pourquoi?

Vous pouvez faire une identité être la PK et avoir l'index en cluster sur rfq_id + action_time + identité et comment cela affecterait-il vraiment votre conception ou toute performance? Il refléterait également mieux que les données ont été ajoutées simultanément (chaque rangée avec la même datetes)


1 commentaires

Eh bien, ça ne me dérange pas de faire un "hack" parce que c'est une requête unique. Je crée la nouvelle table et l'initialise en utilisant des données d'une autre table. Ensuite, il n'y aura que 2 ou 3 enregistrements ajoutés par jours. Donc, je pourrais vivre avec DateTime dans la clé primaire.



1
votes

Ajout que 1 milliseconde ne fonctionnera pas comme les valeurs DateTime dans SQL sont arrondies par incréments de 0,000, 0,003 ou 0,007. Donc, si vous allez ajouter seulement 1 milliseconde dans n'importe quelle valeur de date de la date, il ne fait aucun impact sur la dateTime d'origine.

Vous devez ajouter au moins 2 millisecondes dans la dateTime afin que la nouvelle datetime puisse être arrondie à .003 et vos implications fonctionnent.


0 commentaires