03. marts 2005 - 14:51Der er
11 kommentarer og 1 løsning
Konvertere 'brugerdefineret' til tidsformat
Jeg er ved at overføre nogle data fra et Excel regneark til SQL Server, men er stødt ind i et problem med datoer/tidspunkter. I regnearket er der f.eks. indtastet 12 15 (som er et tidspunkt, selvfølgelig) i en celle som er formateret som Brugerdefineret (00 00) Dette tidspunkt vil jeg gerne have overført til SQL Server som et "rigtigt" tidspunkt (vha. min DTS pakke), men hvordan? Det kan desværre komme på tale at ændre formatet på regnearket, og jeg har forsøgt forskellige datatyper på feltet i tabellen. What to do...?
Med kunstig intelligens skaber HP’s nye OmniBook X 14 en unik og skræddersyet brugeroplevelse målrettet dem, der ønsker høj ydeevne og intelligente funktioner
Jeg ville lave en ekstra kolonne i tabellen hvor jeg gemmer tidspunktet som tekst. Derefter vil jeg køre en SQL der henter den tekst ud, behandler den og inserter den i den rigtige kolonne
Der findes desværre ikke nogen variabel type i sql der hedder time (der må du vente til 2005), det angives som datetime.
Hvis du har en dato i dit Excel ark også, så begynder det at hjælpe på det :O)
Må jeg spørge om hvad du vil opnå ved lige akkurat at opbevare et tidspunkt som time? Skal det forsåes som et interval eller er det bare et tidspunkt på en relativ dag?
Det ville jeg løse ved at lave alle tidspunkter på den samme dag, 1/1 2000 for eksempel. Hvis det kun er klokkeslættet der skal bruges, så er det jo ligegyldigt hvilken dato det er, men det er erimod måske vigtigt at kl 16 er senere end klokken 15.30. så hvis data skal sorteres efter klokkeslæt vil det være en god ide at alle er på samme dato. i sql kan det for eksempel gøres sådan:
Lad os sige at der i kolonnen strTid er tekststrenge, fx. "21 45", og en smalldatetime der hedder dtmTid der skal udfyldes, og vi vedtager at der er NULL i dtmTid for de poster hvor datoen endnu ikke er "ordnet". Så ville jeg lave dette:
UPDATE tabelnavn set dtmTid = CONVERT(datetime, '2000-01-01 ' + LEFT(strTid, 2) + ':' + RIGHT(strTid, 2), 120) WHERE dtmTid IS NULL
ldanielsen-> Både ja og nej, din løsning virker, men ikke optimalt. Det kommer helt an på hvordan tidspunktet skal anvendes. Hvis det blot er en tidsangivelse, så vil det helt sikkert bedre kunne svare sig at droppe den dato som du vil sætte foran. DateTime bruger 8bytes, den smalldatetime som du foreslog bruger 4bytes. Men hvis det som sagt kun er et tidsinterval så ville jeg helt sikkert bare bruge en smallint (2^15) det burde jo være mer end nok :O)
Udover det vil der også ligge en del dårlig performance hvis man havde opbevaret noget med dato foran... Så skulle man måske også lige pludselig til at dele den igen, når man skulle bruge resultatet + som du selv har vist koden til.. en meget performance krævende operation (left-right) + det at tiden formodentlig kan stå på flere måder end bare tt mm
Men lad os nu høre hvad puppetmaster siger om den time benævnelse.
Hvis du laver det som smallint, så kan du ikke få at vide hvor mange minuttr der er mellem kl 1020 og kl 11.35, uden at skulle regne på det. Alt det får du forærende med et dato felt. Men igen, hvis der ikke er brug for det heller, så kan man jo lige så godt lade det være et tekstfelt, skulle jeg mene.
det er rigtigt at MSSQL godt kan konvertere tekst til dato, lige som den kan konvertere tal til tekst og omvendt. Men der er ingen mening i at MSSQL selv skal finde ud af at undersøge tekstformatet for at vurdere hvilket format det er i, det er bare ekstra arbejde. Koden ser mere kompliceret ud, men for programmet er det faktisk mere enkelt at afvikle.
I øvrigt: DECLARE @d smalldatetime SET @d = '23 16'
det giver en fejl, så du er alligevel nødt til at gøre noget ved tekststrengen. Hvis man erstatter mellemrummet med et kolon så virker det:
:( Det ser ikke ud til at være så nemt endda og ydermere så skal jeg hente felter fra et andet regneark, SAMTIDIG, for primærnøglen er en sammensat én. Må bare gemme det som en tekst på 5 tegn. I regnearket er værdierne nemlig en starttid og stoptid, men regnearket regner også tiden derimellem ud, så den overfører jeg også til SQL Serveren (hvis man havde felterne som dato-type, kunne der altid, nemt, kunne beregnes på dem, men nu har jeg tidsforbruget, så må det være godt nok. IKKE optimalt eller særligt "data-sikkert"!)
ldanielsen -> Selvfølgelig kan du få at vide hvor mange minutter der er imellem 1020 og 1245. Du tror sikkert at tidspunktet skal opbevares som du ser det, hvilket jo ikke er tilfældet og absolut heller ikke den korrekte måde at løse sådanne ting på. Tag et kig på Microsoft Time :O)
Og naturligvis bliver du nødt til at replace mellemrummet med ':'! Hvis det nu af uransagelige årsager viser sig at du alligevel vil indsætte en tid vha. den replace så vil den implicitte conversion alligevel være hurtigere end din convert, se her:
drop table #qwe create table #qwe ( t smalldatetime )
insert into #qwe values(replace('12 12', ' ', ':')) /* Trace */ insert into #qwe values(replace('12 12', ' ', ':')) SQL:StmtCompleted 0 0 3 0 Hvilket viser 0reads og 3ms i duration
og dit forslag: declare @t datetime
select @t = CONVERT(datetime, '2000-01-01 ' + replace('12 12', ' ', ':'), 120) insert into #qwe values(@t) /*Trace*/ insert into #qwe values(@t) SQL:StmtCompleted 15 0 27 0 Hvilket viser 27reads og 15ms i duration
puppetmaster-> Idéen med tidsforbruget er nu ikke så tosset endda, hvorfor bruger 2 felter på at vise noget der kan vises i et felt, medmindre tidsforbrugets start og slut skal registreres ligeså.
Jeg har lavet feltet som et datetime, det virker med lidt hiv og sving
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.