imansible trasmettere il valore come float

Abbiamo un SQL che esegue una funzione CAST (su FLOAT) su ColumnA. L’SQL ha un filtro che alla fine filtrerà indirettamente quelle righe che hanno valori non numerici in ColumnA. Tuttavia, a causa di ciò che ritengo sia dovuto all’esecuzione di porzioni di SQL in parallelo, credo che il CAST venga applicato anche alle righe che vengono filtrate e questo causa il fallimento dell’SQL su “imansible eseguire il cast come float … ”

So che se corro con un proc aggiungendo il suggerimento di query

OPTION (MAXDOP 1) 

che l’SQL viene eseguito come previsto. Ho il sospetto che l’esecuzione su 1 proc costringa il filtro ad essere applicato a estirpare la riga con i valori non numerici nella colonnaA in modo che il CASTING dei suoi valori abbia esito positivo. Ho anche trovato che usando il suggerimento di query

 OPTION (FORCE ORDER) 

risolve il problema, sto assumendo perché anche questo assicura che il filtro sia applicato per primo e ottengo prestazioni di query molto migliori rispetto a quelle che si eseguono su un cilindro.

Mi sto appoggiando per risolvere il problema usando la seconda opzione. Se ho idee sbagliate su cosa sta succedendo qui o se qualcuno vorrebbe esporre il mio generale capire o fare una raccomandazione, lo apprezzerei.

Sto correndo

Microsoft SQL Server 2008 R2 (RTM) – 10.50.1720.0 (X64) 12 giugno 2010 01:34:59 Copyright (c) Microsoft Corporation Enterprise Edition (64 bit) su Windows NT 5.2 (Build 3790: Service Pack 2)

Un ripensamento:

Sembra che sarebbe bello se T-SQL avesse le seguenti funzioni da verificare per vedere se una stringa poteva essere convertita in un particolare tipo di dati.

IsFloat IsNumeric IsInteger ecc

Sono davvero infastidito dal numero di colonne di tutti i tipi di dati che trovo nel nostro database definiti come varchar (255). Immagino che la soluzione sia “non farlo!”

Riguardo il tuo dopo pensiero.

Sembra che sarebbe bello se T-SQL avesse le seguenti funzioni da verificare per vedere se una stringa poteva essere convertita in un particolare tipo di dati.

SQL Server 2012 presenta TRY_CONVERT per questa esigenza. Quindi la seguente query restituirebbe NULL piuttosto che un errore.

 SELECT TRY_CONVERT ( FLOAT, 'Fish') 

Non vi è alcuna garanzia nemmeno con i piani seriali che la clausola WHERE si verifichi prima che venga valutata la SELECT . Come spiegato in questo post del blog da SQL Server 2005, è più probabile che ciò avvenga rispetto alle versioni precedenti. Le funzionalità di comportamento delle modifiche al motore di database in SQL Server 2005 lo richiamano specificamente come segue.

SQL Server 2005 a volte valuta le espressioni nelle query prima di quando vengono valutate in SQL Server 2000. Questo comportamento offre i seguenti importanti vantaggi:

  • La capacità di associare gli indici su colonne calcolate a espressioni in una query che sono uguali all’espressione di colonna calcasting.
  • La prevenzione del calcolo ridondante dei risultati di espressione.

Ulteriori discussioni su questo comportamento si trovano in un altro post del blog di Craig Freedman Conversion and Arithmetic Errors .

Nelle versioni precedenti al 2012 e TRY_CONVERT è necessario avvolgere CAST AS FLOAT in un’istruzione CASE . per esempio

  SELECT CASE WHEN ISNUMERIC(Col)=1 THEN CAST(Col AS FLOAT) END AS Col FROM Table WHERE ISNUMERIC(Col)=1 

Questo non è assolutamente garantito per evitare di ottenere errori come ISNUMERIC stesso controlla solo che il valore verrebbe eseguito su uno dei tipi di dati numerici piuttosto che su un valore float Un esempio di un input che fallirebbe è '.'

CASE è documentato per lo più in cortocircuito nei libri online ( alcune eccezioni sono discusse qui )

È inoltre ansible trovare ulteriori discussioni / reclami su questo nella voce di connessione SQL Server non deve generare errori illogici e una buona spiegazione di un problema simile da SQLKiwi

Credo che tu abbia ragione. La funzione CONVERT () viene applicata prima che i predicati “filtrino indirettamente” le righe.

Per evitare l’eccezione, sei corretto, un approccio è tentare di ottenere un minimo di controllo sull’ordine delle operazioni nel piano di esecuzione. Se il suggerimento per l’affermazione funziona per te, allora puoi andare con quello. (Personalmente, i suggerimenti sono l’ultima risorsa per me.)

Si noti che SQL Server ha una funzione IsNumeric.

La funzione IsNumeric è alquanto inadeguata, nel senso che ci sono alcuni valori che “passano” un test IsNumeric ma che generano un’eccezione quando vengono convertiti in un tipo di dati numerico.

Personalmente, tenderei ad adottare questo approccio:

 select convert(float,case when isnumeric( t.foo )=1 then t.foo else null end) 

piuttosto che suggerimenti a livello di istruzione.

Oppure, vorrei specificare gli altri predicati che dovrebbero “filtrare” i valori che non dovrebbero essere convertiti.

 select convert(float,case when t.fi in ('fo','fum') then t.foo else null end)