Als u SQL Server-foutbericht 8117 krijgt met het bericht Operand-gegevenstype varchar is ongeldig voor som-operator , komt dat omdat u het verkeerde gegevenstype doorgeeft aan een operator of functie.
In dit geval geeft de fout aan dat we een tekenreeks doorgeven aan de SUM()
functie. Thij SUM()
functie werkt niet op strings. Het werkt alleen op numerieke typen.
Dezelfde fout (bericht 8117) kan ook in andere contexten voorkomen - het is niet beperkt tot de SUM()
functie.
Voorbeeld van de fout
Hier is een voorbeeld van code die de fout veroorzaakt:
SELECT SUM(ProductName)
FROM Products;
Resultaat:
Msg 8117, Level 16, State 1, Line 1 Operand data type varchar is invalid for sum operator.
In dit geval proberen we de ProductName
. bij elkaar op te tellen kolom.
In dit geval is het zeer waarschijnlijk dat de ProductName
kolom is een varchar
kolom. We hebben waarschijnlijk de verkeerde kolom.
Oplossing 1
Om deze fout op te lossen, moeten we eerst controleren of we de juiste kolom hebben. Als we niet de juiste kolom hebben, verander deze dan in de juiste kolom:
SELECT SUM(Price)
FROM Products;
Hopelijk lost dat het probleem op. Met andere woorden, hopelijk de Price
kolom is numeriek, zoals het hoort.
Maar wat als dat niet zo is?
Oplossing 2
In sommige gevallen kan het zijn dat u de juiste kolom hebt, maar dat die kolom een ongepast gegevenstype gebruikt. Stel bijvoorbeeld dat onze Price
kolom was eigenlijk gedefinieerd als een varchar
kolom.
In dat geval krijgen we dezelfde foutmelding:
SELECT SUM(Price)
FROM Products;
Resultaat:
Msg 8117, Level 16, State 1, Line 1 Operand data type varchar is invalid for sum operator.
Op het eerste gezicht lijkt er niets mis te zijn met deze stelling. We krijgen alleen een totaal van de waarden in de Price
kolom. Dit is een perfect voorbeeld van wat de SUM()
functie is ontworpen om te doen.
De veronderstelling hier is natuurlijk dat de Price
kolom is numeriek. Maar volgens de foutmelding is het niet numeriek - het is een varchar
.
Laten we het gegevenstype van de kolom eens bekijken:
SELECT
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH AS MAX_LENGTH,
CHARACTER_OCTET_LENGTH AS OCTET_LENGTH
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Products'
AND COLUMN_NAME = 'Price';
Resultaat:
+-------------+--------------+----------------+ | DATA_TYPE | MAX_LENGTH | OCTET_LENGTH | |-------------+--------------+----------------| | varchar | 255 | 255 | +-------------+--------------+----------------+
Zoals vermoed is de kolom van het type varchar
.
In dit geval hebben we twee opties; verander het type van de kolom, of converteer het type direct wanneer je de som krijgt.
Laten we het type meteen omzetten:
SELECT SUM(CAST(Price AS decimal(8,2)))
FROM Products;
Resultaat:
48.25
Dit werkte gelukkig.
In dit geval zijn alle gegevens in de Price
kolom kan worden geconverteerd naar een numeriek type.
Als u een foutmelding krijgt Msg 8114 die iets leest als Fout bij het converteren van gegevenstype varchar naar numeriek , dan betekent dit dat de kolom gegevens bevat die niet naar numeriek kunnen worden geconverteerd.
De fout ziet er als volgt uit:
Msg 8114, Level 16, State 5, Line 1 Error converting data type varchar to numeric.
In dit geval moet u de niet-numerieke gegevens vinden en beslissen wat u ermee gaat doen.
Zo kunnen we de niet-numerieke waarden vinden:
SELECT Price
FROM Products
WHERE ISNUMERIC(Price) <> 1;
Resultaat:
+-------------+ | Price | |-------------| | Ten dollars | | Fifteen | +-------------+
We hebben de boosdoeners gevonden!
Tenzij er een goede reden is om dat niet te doen, moeten we die waarden veranderen in hun numerieke equivalenten.
Daarna moeten we overwegen het gegevenstype van de kolom te wijzigen, zodat dit type gegevens in de toekomst niet kan worden ingevoegd. Als u dit doet, wordt de gegevensintegriteit afgedwongen.
Eén ding om op te letten bij het gebruik van de ISNUMERIC()
functie is dat het soms valse positieven kan retourneren. Wat ik bedoel is dat er enkele niet-numerieke tekens zijn die als numeriek worden geïnterpreteerd. Zie niet-cijferige tekens die positief retourneren bij gebruik van ISNUMERIC()
voor meer hierover.