Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of mappen te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen om mappen te wijzigen.
Van toepassing op:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Azure Synapse Analytics
SQL Analytics-eindpunt in Microsoft Fabric
Magazijn in Microsoft Fabric
SQL-database in Microsoft Fabric
Met deze functies wordt een expressie van het ene gegevenstype geconverteerd naar het andere.
Syntaxis
CAST syntaxis:
CAST ( expression AS data_type [ ( length ) ] )
CONVERT syntaxis:
CONVERT ( data_type [ ( length ) ] , expression [ , style ] )
Transact-SQL syntaxis-conventies
Argumenten
expressie
Elke geldige expressie.
data_type
Het doelgegevenstype. Dit omvat xml, bigint en sql_variant. Aliasgegevenstypen kunnen niet worden gebruikt.
lengte
Een optioneel geheel getal dat de lengte van het doelgegevenstype aangeeft, voor gegevenstypen die een door de gebruiker opgegeven lengte toestaan. De standaardwaarde is 30.
stijl
Een gehele expressie die specificeert hoe de CONVERT functie de expressie vertaalt. Voor een stijlwaarde van NULLwordt teruggegeven NULL .
data_type bepaalt het bereik.
Retourtypen
Retourneert expressie, vertaald naar data_type.
Datum- en tijdstijlen
Voor een datum- of tijdgegevenstypeexpressie kan de stijl een van de waarden bevatten die worden weergegeven in de volgende tabel. Andere waarden worden verwerkt als 0. Vanaf SQL Server 2012 (11.x) zijn de enige stijlen die worden ondersteund bij het omzetten van datum- en tijdtypes naar datetimeoffset, of 01. Alle andere conversiestijlen retourneren fout 9809.
Opmerking
De SQL Server Database Engine ondersteunt het datumformaat, in Arabische stijl, met het Koeweitse algoritme.
| Zonder eeuw (yy) 1 | Met eeuw (jjjj) | Standaard | Invoer/uitvoer 3 |
|---|---|---|---|
| - |
0of 1001,2 |
Standaardinstelling voor datum/tijd en smalldatetime |
MMM dd yyyy hh:mmtt (tt is AM of PM) |
1 |
101 |
VS | 1 = MM/dd/yy101 = MM/dd/yyyy |
2 |
102 |
American National Standards Institute (ANSI) | 2 = yy.MM.dd102 = yyyy.MM.dd |
3 |
103 |
Brits/Frans | 3 = dd/MM/yy103 = dd/MM/yyyy |
4 |
104 |
Duits | 4 = dd.MM.yy104 = dd.MM.yyyy |
5 |
105 |
Italiaans | 5 = dd-MM-yy105 = dd-MM-yyyy |
6 |
106
1 |
- | 6 = dd MMM yy106 = dd MMM yyyy |
7 |
107
1 |
- | 7 = MMM dd, yy107 = MMM dd, yyyy |
8 of 24 |
108 |
- | HH:mm:ss |
| - |
9of 1091,2 |
Standaard + milliseconden |
MMM dd yyyy hh:mm:ss:ffftt (tt is AM of PM) |
10 |
110 |
Verenigde Staten van Amerika | 10 = MM-dd-yy110 = MM-dd-yyyy |
11 |
111 |
Japan | 11 = yy/MM/dd111 = yyyy/MM/dd |
12 |
112 |
ISO | 12 = yyMMdd112 = yyyyMMdd |
| - |
13of 1131,2 |
Standaardwaarde van Europa + milliseconden |
dd MMM yyyy HH:mm:ss:fff (24 uur) |
14 |
114 |
- |
HH:mm:ss:fff (24 uur) |
| - |
20 of 1202 |
ODBC-canoniek |
yyyy-MM-dd HH:mm:ss (24 uur) |
| - |
21of 25of121 2 |
ODBC canonical (met milliseconden) standaard voor tijd, datum, datum/tijd2 en datetimeoffset |
yyyy-MM-dd HH:mm:ss.fff (24 uur) |
22 |
- | VS |
MM/dd/yy hh:mm:ss tt (tt is AM of PM) |
| - | 23 |
ISO8601 | yyyy-MM-dd |
| - |
126
4 |
ISO8601 |
yyyy-MM-ddTHH:mm:ss.fff (geen spaties) 6 |
| - |
127
8, 9 |
ISO8601 met tijdzone Z |
yyyy-MM-ddTHH:mm:ss.fffZ (geen spaties) 6 |
| - |
130
1,2 |
Hijri 5 |
dd MMMM yyyy hh:mm:ss:ffftt
7 |
| - |
131
2 |
Hijri 5 | dd/MM/yyyy hh:mm:ss:ffftt |
1 Deze stijlwaarden retourneren niet-deterministische resultaten. Bevat alle (yy) (zonder eeuw) stijlen en een subset van () (yyyymet eeuw) stijlen.
2 De standaardwaarden (0 of 100, of 9109, of 113, 13 of , 20 , 23, 120, en 21 of 25 of 121) geven altijd de century (yyyy) terug.
Belangrijk
Standaard interpreteert de SQL Server Database Engine tweecijferige jaren op basis van een cutoffjaar van 2049. Dat betekent dat de Database Engine het tweecijferige jaar 49 interpreteert als 2049 en het tweecijferige jaar 50 als 1950. Veel clienttoepassingen, inclusief toepassingen op basis van Automation-objecten, gebruiken een cutoff jaar 2030. De Database Engine biedt de tweecijferige afkapdatum configuratieoptie om het afkapjaar dat door de Database Engine wordt gebruikt te wijzigen. Dit zorgt voor een consistente behandeling van datums. We raden u aan viercijferige jaren op te geven.
3 Invoer wanneer u converteert naar datum/tijd; uitvoer wanneer u converteert naar tekengegevens.
4 Ontworpen voor XML-gebruik. Zie de vorige tabel voor de uitvoerindeling voor conversie van datum/tijd of smalldatetime naar tekengegevens.
5 Hijri is een kalendersysteem met verschillende variaties. De Database Engine gebruikt het Koeweitse algoritme.
6 Voor een milliseconden (fff) waarde van 0 wordt de decimale breukwaarde van milliseconden niet weergegeven. De waarde 2022-11-07T18:26:20.000 wordt bijvoorbeeld weergegeven als 2022-11-07T18:26:20.
7 In deze stijl MMMM vertegenwoordigt u een Hijri Unicode-weergave met meerdere tokens van de volledige maandnaam. Deze waarde wordt niet correct weergegeven bij een standaard-AMERIKAANSE installatie van SSMS.
8 Alleen ondersteund bij het casten van tekengegevens naar datum/tijd of smalldatetime. Bij het casten van tekengegevens die alleen datum- of alleen tijdonderdelen vertegenwoordigen voor de gegevenstypen datum/tijd of smalldatetime , wordt het niet-opgegeven tijdonderdeel ingesteld 00:00:00.000op en wordt het niet-opgegeven datumonderdeel ingesteld op 1900-01-01.
9 Gebruik de optionele tijdzone-indicator Z om het eenvoudiger te maken om XML-datumtijdwaarden met tijdzone-informatie toe te wijzen aan de Database Engine datumtijdwaarden zonder tijdzone.
Z geeft de tijdzone aan op UTC-0. De HH:mm offset, in de + of - richting, geeft andere tijdzones aan. Voorbeeld: 2022-12-12T23:45:12-08:00.
Wanneer u smalldatetime converteert naar tekengegevens, worden in de stijlen met seconden of milliseconden nullen in deze posities weergegeven. Bij het converteren van datum/tijd - of smalldatetime-waarden gebruikt u een geschikte teken - of varchar-gegevenstypelengte om ongewenste datumonderdelen af tekappen.
Bij het converteren van tekengegevens naar datetimeoffset, met behulp van een stijl die een tijd bevat, wordt een tijdzoneverschil toegevoegd aan het resultaat.
float en echte stijlen
Voor een float - of echteexpressie kan de stijl een van de waarden bevatten die in de volgende tabel worden weergegeven. Andere waarden worden verwerkt als 0.
| Waarde | Uitvoer |
|---|---|
0 (standaard) |
Maximaal 6 cijfers. Gebruik in wetenschappelijke notatie, indien van toepassing. |
1 |
Altijd 8 cijfers. Gebruik altijd in wetenschappelijke notatie. |
2 |
Altijd 16 cijfers. Gebruik altijd in wetenschappelijke notatie. |
3 |
Altijd 17 cijfers. Gebruiken voor verliesloze conversie. Met deze stijl wordt gegarandeerd elke afzonderlijke float of echte waarde geconverteerd naar een afzonderlijke tekenreeks. Van toepassing op: SQL Server 2016 (13.x) en latere versies en Azure SQL Database. |
126, 128, 129 |
Opgenomen om verouderde redenen. Gebruik deze waarden niet voor nieuwe ontwikkeling. |
geld en smallmoney stijlen
Voor een geld- of smallmoney-expressie kan stijl een van de waarden bevatten die worden weergegeven in de volgende tabel. Andere waarden worden verwerkt als 0.
| Waarde | Uitvoer |
|---|---|
0 (standaard) |
Geen komma's om de drie cijfers links van het decimaalteken en twee cijfers rechts van het decimaalteken Voorbeeld: 4235.98. |
1 |
Komma's om de drie cijfers links van het decimaalteken en twee cijfers rechts van het decimaalteken Voorbeeld: 3510,92. |
2 |
Geen komma's om de drie cijfers links van het decimaalteken en vier cijfers rechts van het decimaalteken Voorbeeld: 4235.9819. |
126 |
Equivalent aan stijl 2, wanneer men omzet naar char(n) of varchar(n) |
XML-stijlen
Voor een XML-expressie kan de stijl een van de waarden bevatten die worden weergegeven in de volgende tabel. Andere waarden worden verwerkt als 0.
| Waarde | Uitvoer |
|---|---|
0 (standaard) |
Gebruik standaardparseringsgedrag dat onbelangrijke witruimte negeert en geen interne DTD-subset toestaat. Opmerking: Bij het converteren naar het xml-datatype behandelt de Database Engine onbeduidende witte ruimte anders dan XML 1.0. Voor meer informatie, zie Create instances of XML data. |
1 |
Onbeduidende witruimte behouden. Met deze stijlinstelling wordt de standaardafhandeling xml:space ingesteld zodat deze overeenkomt met het gedrag van xml:space="preserve". |
2 |
Schakel beperkte interne DTD-subsetverwerking in. Indien ingeschakeld, kan de server de volgende informatie gebruiken die is opgegeven in een interne DTD-subset om niet-validerende parseringsbewerkingen uit te voeren. - Standaardwaarden voor kenmerken worden toegepast - Interne entiteitsverwijzingen worden omgezet en uitgevouwen - Het DTD-inhoudsmodel wordt gecontroleerd op syntactische juistheid De parser negeert externe DTD-subsets. Ook evalueert het de XML-declaratie niet om te zien of het standalone attribuut een yes of of no heeft. In plaats daarvan wordt het XML-exemplaar geparseerd als een zelfstandig document. |
3 |
Behoud onbeduidende witruimte en schakel beperkte interne DTD-subsetverwerking in. |
Binaire stijlen
Voor een binaire(n), char(n), varbinary(n)- of varchar(n)-expressie kan de stijl een van de waarden bevatten die worden weergegeven in de volgende tabel. Stijlwaarden die niet in de tabel staan, geven een foutmelding.
| Waarde | Uitvoer |
|---|---|
0 (standaard) |
Hiermee worden ASCII-tekens omgezet in binaire bytes of binaire bytes naar ASCII-tekens. Elk teken of elke byte wordt geconverteerd 1:1. Voor een binaire data_type worden de tekens 0x links van het resultaat toegevoegd. |
1, 2 |
Voor een binair data_type moet de expressie een tekenexpressie zijn. De uitdrukking moet een even aantal hexadecimale cijfers hebben (0, , 1, 32, , 4, ). f56789ABCDEFabcde Als de stijl is ingesteld op 1, moet de uitdrukking als de eerste twee tekens zijn 0x . Als de expressie een oneven aantal tekens bevat of als een van de tekens ongeldig is, wordt er een fout gegenereerd.Als de lengte van de geconverteerde expressie de lengte van de data_type overschrijdt, wordt het resultaat afgekapt. Vaste lengte data_typegroter is dan het geconverteerde resultaat heeft nullen toegevoegd aan de rechterkant van het resultaat. Voor een data_type van het type teken is een binaire expressie vereist. Elk binair teken wordt geconverteerd naar twee hexadecimale tekens. Stel dat de lengte van de geconverteerde expressie groter is dan de lengte van de data_type. In dat geval wordt het afgekapt. Voor een type vaste grootte data_type, als de lengte van het geconverteerde resultaat kleiner is dan de lengte van de data_type, worden spaties toegevoegd aan de rechterkant van de geconverteerde expressie om een even aantal hexadecimale cijfers te behouden. De personages 0x worden niet links van het geconverteerde resultaat toegevoegd voor de stijl2. |
Impliciete conversies
Voor impliciete conversies is geen specificatie van de CAST functie of de CONVERT functie vereist. Voor expliciete conversies is een specificatie van de CAST functie of de CONVERT functie vereist. De volgende illustratie toont alle expliciete en impliciete datatypeconversies die zijn toegestaan voor de door het Database Engine systeem geleverde datatypes. Deze omvatten bigint, sql_variant, xml, hierarchyid, geography, geometry, json en vector. De json- en vectordatatypes zijn alleen beschikbaar in SQL Server 2025 (17.x), Azure SQL Database, Azure SQL Managed Instance en SQL database in Microsoft Fabric. Er is geen impliciete conversie bij toewijzing van het sql_variant datatype, maar wel impliciete conversie naar sql_variant.
De bovenstaande grafiek illustreert alle expliciete en impliciete conversies die in de Database Engine zijn toegestaan, maar het resulterende datatype van de conversie hangt af van de uitgevoerde bewerking:
- Voor expliciete conversies bepaalt de instructie zelf het resulterende gegevenstype.
- Voor impliciete conversies, zoals het instellen van de waarde van een variabele of het invoegen van een waarde in een kolom, resulteert dit in het gegevenstype dat is gedefinieerd door de variabeledeclaratie of kolomdefinitie.
- Voor vergelijkingsoperatoren of andere expressies is het resulterende gegevenstype afhankelijk van de regels van de prioriteit van het gegevenstype.
Voor sommige datatypen hangt het resultaat af van hoe het datatype wordt gedeclareerd:
-
Decimaal en numeriek: De Database Engine behandelt elke combinatie van precisie en schaal als een ander datatype. Conversie tussen hen kan impliciet zijn. Een waarde met meer decimalen dan de doelschaal wordt zonder fout afgerond. Een waarde die te groot is voor de doelprecisie veroorzaakt fout 8115, tenzij
ARITHABORTenANSI_WARNINGSbeideOFFzijn ; dan isNULLhet resultaat . - Je kunt varchar(max),nvarchar(max) en varbinary(max) niet omzetten naar sql_variant.
- Conversie tussen verschillende door de gebruiker gedefinieerde CLR-types is niet toegestaan.
- Impliciete conversie wordt ondersteund tussen ongetypeerde xml en getypte xml, en tussen getypte xml-waarden die dezelfde XML-schemacollectie en hetzelfde
DOCUMENTofCONTENTfacet gebruiken. - Conversie tussen verschillende XML-schemacollecties, of tussen verschillende
DOCUMENTenCONTENTfacetten, moet expliciet zijn. Conversie tussen een CLR-gebruikersgedefinieerd type en getypte xml is niet toegestaan. - Omzetting tussen vectorwaarden is alleen toegestaan wanneer de afmetingen en het basistype (float32 of float16) hetzelfde zijn.
Een conversie die de grafiek als toegestaan toont, kan nog steeds falen voor een specifieke waarde, bijvoorbeeld een string die niet geldig is in JSON, of een vector met een ander aantal dimensies. Waarden van de afbeelding-, ntext-, text-, xml-, geografie-, geometrie-, json- en vectordatatypes kunnen niet worden vergeleken met de operator gelijk aan (=), zelfs niet als beide waarden hetzelfde datatype hebben.
Aanbeveling
Een praktisch voorbeeld van de effecten van prioriteit van het gegevenstype in conversies vindt u verderop in deze sectie.
Wanneer u converteert tussen datetimeoffset en tekentypen teken, nchar, nvarchar en varchar, moet het geconverteerde tijdzoneverschildeel altijd dubbele cijfers hebben voor zowel als HHmm. Bijvoorbeeld: -08:00.
De datatypes nchar en nvarchar slaan Unicode-gegevens op in UTF-16-codering, die altijd een even aantal bytes gebruikt. Wees voorzichtig wanneer je binaire of varbinaire convertert naar of van nchar of nvarchar. Bijvoorbeeld, de volgende conversie geeft geen hexadecimale waarde van 41op. Het geeft een hexadecimale waarde van 4100:
SELECT CAST (CAST (0x41 AS NVARCHAR) AS VARBINARY);
Zie Sortering en Unicode-ondersteuningvoor meer informatie.
Gegevenstypen met een grote waarde
Gegevenstypen met een grote waarde hebben hetzelfde impliciete en expliciete conversiegedrag als hun kleinere tegenhangers, met name de gegevenstypen nvarchar, varbinary en varchar . Houd echter rekening met de volgende richtlijnen:
- Conversie van afbeelding naar varbinary(max), en vice versa, werkt als een impliciete conversie, net als conversies tussen tekst en varchar(max), en ntext en nvarchar(max).
- Conversie van gegevenstypen met een grote waarde, zoals varchar(max), naar een kleiner gegevenstype van een tegenhanger, zoals varchar, is een impliciete conversie, maar afkapping vindt plaats als de grootte van de grote waarde groter is dan de opgegeven lengte van het kleinere gegevenstype.
- De conversie van nvarchar, varbinary of varchar naar de bijbehorende gegevenstypen met een grote waarde vindt impliciet plaats.
- Conversie van het sql_variant gegevenstype naar de gegevenstypen met een grote waarde is een expliciete conversie.
- Gegevenstypen met een grote waarde kunnen niet worden geconverteerd naar het sql_variant gegevenstype.
Voor meer informatie over conversie van het xml-datatype , zie Create instances of XML data.
xml-gegevenstype
Wanneer u het XML-gegevenstype expliciet of impliciet naar een tekenreeks of binair gegevenstype cast, wordt de inhoud van het XML-gegevenstype geserialiseerd op basis van een gedefinieerde set regels. Voor informatie over deze regels, zie Definieer de serialisatie van XML-data. Voor informatie over conversie van andere datatypes naar het xml-datatype , zie Create instances of XML data.
typen tekst- en afbeeldingsgegevens
De typen tekst - en afbeeldingsgegevens bieden geen ondersteuning voor automatische conversie van gegevenstypen. U kunt tekstgegevens expliciet converteren naar tekengegevens en afbeeldingsgegevens naar binair of varbinair, maar de maximale lengte is 8000 bytes. Als je een verkeerde conversie probeert, bijvoorbeeld het omzetten van een karakteruitdrukking met letters naar een int, geeft de Database Engine een foutmelding terug.
Uitvoersortering
Wanneer de CAST of CONVERT functies een tekenreeks uitvoeren en ze een tekenreeksinvoer ontvangen, heeft de uitvoer hetzelfde sorterings- en sorteringslabel als de invoer. Als de invoer geen tekenreeks is, heeft de uitvoer de standaardsortering van de database en een sorteringslabel van coercible-default. Zie sorteringsprioriteitvoor meer informatie.
Om een andere collatie aan de output toe te wijzen, pas je de COLLATE clausule toe op de resultaatuitdrukking van de CAST of-functie CONVERT . Voorbeeld:
SELECT CAST ('abc' AS VARCHAR (5)) COLLATE French_CS_AS;
Resultaten afkappen en afronden
Bij het converteren van tekens of binaire expressies (binair, teken, nchar, nvarchar, varbinary of varchar) naar een expressie van een ander gegevenstype, kan de conversiebewerking de uitvoergegevens afkappen, slechts gedeeltelijk de uitvoergegevens weergeven of een fout retourneren. Deze gevallen ontstaan als het resultaat te kort is om weer te geven. Conversies naar binair,teken, nchar, nvarchar, varbinary of varchar worden afgekapt, met uitzondering van de conversies die in de volgende tabel worden weergegeven.
| Van gegevenstype | Naar gegevenstype | Resultaat |
|---|---|---|
| int, smallint of tinyint |
teken varchar |
Te kort om weer te geven |
|
nchar nvarchar |
Fout 1 | |
| geld, smallmoney, numeriek, decimaal, zwevend of echt |
teken varchar |
Fout 1 |
|
nchar nvarchar |
Fout 1 |
1 Fout geretourneerd omdat de resultaatlengte te kort is om weer te geven.
De SQL Server Database Engine garandeert dat alleen roundtrip-conversies, met andere woorden conversies die een datatype van het oorspronkelijke datatype omzetten en weer terug, dezelfde waarden van versie tot versie opleveren. In het volgende voorbeeld ziet u een dergelijke retourconversie:
DECLARE @myval AS DECIMAL (5, 2);
SET @myval = 193.57;
SELECT CAST (CAST (@myval AS VARBINARY (20)) AS DECIMAL (10, 5));
-- Or, using CONVERT
SELECT CONVERT (DECIMAL (10, 5), CONVERT (VARBINARY (20), @myval));
GO
Waarschuwing
Bouw geen binaire waarden en converteer ze vervolgens naar een gegevenstype van de categorie numeriek gegevenstype. De Database Engine garandeert niet dat het resultaat van een decimale of numerieke datatype-omzetting naar binair hetzelfde is tussen versies van SQL Server.
In het volgende voorbeeld ziet u een resulterende expressie die te klein is om weer te geven.
USE AdventureWorks2025;
GO
SELECT p.FirstName,
p.LastName,
SUBSTRING(p.Title, 1, 25) AS Title,
CAST (e.SickLeaveHours AS CHAR (1)) AS [Sick Leave]
FROM HumanResources.Employee AS e
INNER JOIN Person.Person AS p
ON e.BusinessEntityID = p.BusinessEntityID
WHERE NOT e.BusinessEntityID > 5;
GO
Hier is het resultatenoverzicht.
FirstName LastName Title Sick Leave
--------- ------------- ------- --------`
Ken Sanchez NULL *
Terri Duffy NULL *
Roberto Tamburello NULL *
Rob Walters NULL *
Gail Erickson Ms. *
Wanneer je datatypes converteert die op decimalen verschillen, geeft de Database Engine soms een afgeknotte resultaatwaarde terug, en op andere momenten een afgeronde waarde. In deze tabel ziet u het gedrag.
| Van | Tot | Gedrag |
|---|---|---|
| numeriek | numeriek | Ronde |
| numeriek | Int | Afbreken |
| numeriek | geld | Ronde |
| geld | Int | Ronde |
| geld | numeriek | Ronde |
| drijven | Int | Afbreken |
| drijven | numeriek | Ronde 1 |
| drijven | datum en tijd | Ronde |
| datum en tijd | Int | Ronde |
1 De conversie van floatwaarden die gebruikmaken van wetenschappelijke notatie naar decimale of numerieke waarden is beperkt tot alleen waarden van precisie 17 cijfers. Elke waarde met precisie die hoger is dan 17 rondt af op nul.
Bijvoorbeeld, de waarden 10,6496 en -10,6496 kunnen worden afgekapt of afgerond tijdens de omzetting naar int- of numerieke types:
SELECT CAST (10.6496 AS INT) AS trunc1,
CAST (-10.6496 AS INT) AS trunc2,
CAST (10.6496 AS NUMERIC) AS round1,
CAST (-10.6496 AS NUMERIC) AS round2;
De resultaten van de query worden weergegeven in de volgende tabel:
| trunc1 | trunc2 | round1 | round2 |
|---|---|---|---|
| 10 | -10 | 11 | -11 |
Wanneer u gegevenstypen converteert waarbij het doelgegevenstype minder decimalen heeft dan het brongegevenstype, wordt de waarde afgerond. Deze conversie retourneert $10.3497bijvoorbeeld:
SELECT CAST (10.3496847 AS MONEY);
De Database Engine geeft een foutmelding terug bij het omzetten van niet-numerieke char-, nchar-, nvarchar- of varchar-gegevens naar decimaal, float,int, numeriek. De Database Engine geeft ook een foutmelding wanneer een lege string ( ) wordt omgezet naar numeriek of decimaal.
Bepaalde datum/tijd-conversies zijn niet-deterministisch
De stijlen waarvoor de conversie van tekenreeks tot datum/tijd niet-deterministisch is, zijn als volgt:
- Alle stijlen onder
1001 106107109113130
1 Met uitzondering van stijlen 20 en 21
Zie Niet-deterministische conversie van letterlijke datumtekenreeksen in DATUM-waardenvoor meer informatie.
Aanvullende tekens (surrogaatparen)
Vanaf SQL Server 2012 (11.x) worden bij het gebruik van sc-sorteringen (aanvullende tekens) een CAST bewerking van nchar of nvarchar naar een nchar- of nvarchar-type kleinere lengte niet afgekapt binnen een surrogaatpaar. In plaats daarvan wordt de bewerking afgekapt vóór het aanvullende teken. Het volgende codefragment blijft @x bijvoorbeeld gewoon abin stand. Er is onvoldoende ruimte om het aanvullende teken vast te houden.
DECLARE @x AS NVARCHAR (10) = 'ab' + NCHAR(0x10000);
SELECT CAST (@x AS NVARCHAR (3));
Bij het gebruik van SC-sorteringen is het gedrag van CONVERT, vergelijkbaar met die van CAST. Zie Sortering en Unicode-ondersteuning voor aanvullende tekens voor meer informatie.
Compatibiliteitsondersteuning
In eerdere versies van SQL Server is 121de standaardstijl voor CAST en bewerkingen CONVERT op tijd- en datumtijd2-datatypes , behalve wanneer een van beide typen wordt gebruikt in een berekende kolomexpressie. Voor berekende kolommen is 0de standaardstijl . Dit gedrag beïnvloedt berekende kolommen wanneer ze worden aangemaakt, gebruikt in queries met auto-parameterisatie, of gebruikt in constraintdefinities.
Onder compatibiliteitsniveau110 en hoger hebben 121 de CAST en CONVERT bewerkingen op de tijd- en datumtijd2-datatypes altijd de standaardstijl. Als een query afhankelijk is van het oude gedrag, gebruik dan een compatibiliteitsniveau kleiner dan 110, of specificeer expliciet de 0 stijl in de betreffende query.
| Waarde voor compatibiliteitsniveau | Standaardstijl voor CAST en CONVERT1 |
Standaardstijl voor berekende kolom |
|---|---|---|
< 110 |
121 |
0 |
>= 110 |
121 |
121 |
1 Behalve berekende kolommen
Het upgraden van de database naar compatibiliteitsniveau 110 en hoger verandert geen gebruikersgegevens die op schijf zijn opgeslagen. U moet deze gegevens naar wens handmatig corrigeren. Als je SELECT INTO bijvoorbeeld een tabel zou maken van een bron met een hierboven beschreven berekende kolomexpressie, zou de data (met stijl 0) worden opgeslagen in plaats van de berekende kolomdefinitie zelf. Je moet deze gegevens handmatig bijwerken zodat ze de stijl 121overeenkomen.
Voorbeelden
De codevoorbeelden in dit artikel gebruiken de AdventureWorks2025, AdventureWorksDW2025, of AdventureWorksLT2025 voorbeelddatabase, die je kunt downloaden van de Azure Data SQL Samples Repository GitHub-repository.
Eén. Zowel CAST als CONVERT gebruiken
Deze voorbeelden halen de naam van het product op, voor producten die een 3 als het eerste cijfer van de catalogusprijs hebben en converteert hun ListPrice waarden naar int.
Gebruik CAST:
USE AdventureWorks2025;
GO
SELECT SUBSTRING(Name, 1, 30) AS ProductName,
ListPrice
FROM Production.Product
WHERE CAST (ListPrice AS INT) LIKE '33%';
GO
Gebruik CONVERT:
USE AdventureWorks2025;
GO
SELECT SUBSTRING(Name, 1, 30) AS ProductName,
ListPrice
FROM Production.Product
WHERE CONVERT (INT, ListPrice) LIKE '33%';
GO
Hier is het resultatenoverzicht. De voorbeeldresultatenset is hetzelfde voor zowel CASTCONVERTals .
ProductName ListPrice
------------------------------ ---------------------
LL Road Frame - Black, 58 337.22
LL Road Frame - Black, 60 337.22
LL Road Frame - Black, 62 337.22
LL Road Frame - Red, 44 337.22
LL Road Frame - Red, 48 337.22
LL Road Frame - Red, 52 337.22
LL Road Frame - Red, 58 337.22
LL Road Frame - Red, 60 337.22
LL Road Frame - Red, 62 337.22
LL Road Frame - Black, 44 337.22
LL Road Frame - Black, 48 337.22
LL Road Frame - Black, 52 337.22
Mountain-100 Black, 38 3374.99
Mountain-100 Black, 42 3374.99
Mountain-100 Black, 44 3374.99
Mountain-100 Black, 48 3374.99
HL Road Front Wheel 330.06
LL Touring Frame - Yellow, 62 333.42
LL Touring Frame - Blue, 50 333.42
LL Touring Frame - Blue, 54 333.42
LL Touring Frame - Blue, 58 333.42
LL Touring Frame - Blue, 62 333.42
LL Touring Frame - Yellow, 44 333.42
LL Touring Frame - Yellow, 50 333.42
LL Touring Frame - Yellow, 54 333.42
LL Touring Frame - Yellow, 58 333.42
LL Touring Frame - Blue, 44 333.42
HL Road Tire 32.60
B. CAST gebruiken met rekenkundige operatoren
In dit voorbeeld wordt één kolomberekening (Computed) berekend door de totale omzet van het jaar tot heden (SalesYTD) te delen door het commissiepercentage (CommissionPCT). Deze waarde wordt afgerond op het dichtstbijzijnde gehele getal en wordt vervolgens CAST afgerond op een gegevenstype int .
USE AdventureWorks2025;
GO
SELECT CAST (ROUND(SalesYTD / CommissionPCT, 0) AS INT) AS Computed
FROM Sales.SalesPerson
WHERE CommissionPCT != 0;
GO
Hier is het resultatenoverzicht.
Computed
------
379753754
346698349
257144242
176493899
281101272
0
301872549
212623750
298948202
250784119
239246890
101664220
124511336
97688107
C. CAST gebruiken om samen te voegen
In dit voorbeeld worden niet-tekenexpressies samengevoegd met behulp van CAST. De database wordt gebruikt AdventureWorksDW2025 .
SELECT 'The list price is ' + CAST (ListPrice AS VARCHAR (12)) AS ListPrice
FROM dbo.DimProduct
WHERE ListPrice BETWEEN 350.00 AND 400.00;
Hier is het resultatenoverzicht.
ListPrice
------------------------
The list price is 357.06
The list price is 364.09
The list price is 364.09
The list price is 364.09
The list price is 364.09
D. CAST gebruiken om leesbare tekst te produceren
Dit voorbeeld gebruikt CAST in de SELECT lijst om de Name kolom om te zetten naar een kolom char(10). De database wordt gebruikt AdventureWorksDW2025 .
SELECT DISTINCT CAST (EnglishProductName AS CHAR (10)) AS Name,
ListPrice
FROM dbo.DimProduct
WHERE EnglishProductName LIKE 'Long-Sleeve Logo Jersey, M';
GO
Hier is het resultatenoverzicht.
Name ListPrice
---------- ---------
Long-Sleev 31.2437
Long-Sleev 32.4935
Long-Sleev 49.99
E. CAST gebruiken met de LIKE-component
In dit voorbeeld worden de money kolomwaarden SalesYTD geconverteerd naar gegevenstype int en vervolgens naar gegevenstype char(20), zodat de LIKE component deze kan gebruiken.
USE AdventureWorks2025;
GO
SELECT p.FirstName,
p.LastName,
s.SalesYTD,
s.BusinessEntityID
FROM Person.Person AS p
INNER JOIN Sales.SalesPerson AS s
ON p.BusinessEntityID = s.BusinessEntityID
WHERE CAST (CAST (s.SalesYTD AS INT) AS CHAR (20)) LIKE '2%';
GO
Hier is het resultatenoverzicht.
FirstName LastName SalesYTD BusinessEntityID
---------------- ------------------- ---------------- -------------
Tsvi Reiter 2811012.7151 279
Syed Abbas 219088.8836 288
Rachel Valdez 2241204.0424 289
F. CONVERTEREN of CAST gebruiken met getypte XML
Deze voorbeelden tonen het gebruik van CONVERT om data om te zetten naar getypte XML, door gebruik te maken van het xml-datatype en de kolommen (SQL Server).
In dit voorbeeld wordt een tekenreeks met witruimte, tekst en markeringen geconverteerd naar getypte XML en wordt alle onbelangrijke witruimte (grens witruimte tussen knooppunten) verwijderd:
SELECT CONVERT (XML, '<root><child/></root>');
In dit voorbeeld wordt een vergelijkbare tekenreeks met witruimte, tekst en markeringen geconverteerd naar getypte XML en blijft onbelangrijke witruimte behouden (grensspaties tussen knooppunten):
SELECT CONVERT (XML, '<root> <child/> </root>', 1);
In dit voorbeeld wordt een tekenreeks met witruimte, tekst en markeringen omgezet in getypte XML:
SELECT CAST ('<Name><FName>Carol</FName><LName>Elliot</LName></Name>' AS XML);
Zie Create instances of XML data voor meer voorbeelden.
G. CAST en CONVERT gebruiken met datum/tijd-gegevens
GETDATE() Vanaf waarden worden in dit voorbeeld de huidige datum en tijd weergegeven, gebruikt CAST om de huidige datum en tijd te wijzigen in een gegevenstype teken en wordt vervolgens gebruikt CONVERT om de datum en tijd in de ISO 8601 notatie weer te geven.
SELECT GETDATE() AS UnconvertedDateTime,
CAST (GETDATE() AS NVARCHAR (30)) AS UsingCast,
CONVERT (NVARCHAR (30), GETDATE(), 126) AS UsingConvertTo_ISO8601;
GO
Hier is het resultatenoverzicht.
UnconvertedDateTime UsingCast UsingConvertTo_ISO8601
----------------------- ---------------------- ------------------------------
2022-04-18 09:58:04.570 Apr 18 2022 9:58AM 2022-04-18T09:58:04.570
Dit voorbeeld is ongeveer het tegenovergestelde van het vorige voorbeeld. In dit voorbeeld wordt een datum en tijd weergegeven als tekengegevens, wordt gebruikt CAST om de tekengegevens te wijzigen in het gegevenstype datum/tijd en wordt vervolgens gebruikt CONVERT om de tekengegevens te wijzigen in het gegevenstype Datum/tijd .
SELECT '2006-04-25T15:50:59.997' AS UnconvertedText,
CAST ('2006-04-25T15:50:59.997' AS DATETIME) AS UsingCast,
CONVERT (DATETIME, '2006-04-25T15:50:59.997', 126) AS UsingConvertFrom_ISO8601;
GO
Hier is het resultatenoverzicht.
UnconvertedText UsingCast UsingConvertFrom_ISO8601
----------------------- ----------------------- ------------------------
2006-04-25T15:50:59.997 2006-04-25 15:50:59.997 2006-04-25 15:50:59.997
H. CONVERTEREN gebruiken met binaire en tekengegevens
In deze voorbeelden ziet u de resultaten van binaire en tekengegevensconversie, met behulp van verschillende stijlen.
--Convert the binary value 0x4E616d65 to a character value.
SELECT CONVERT (CHAR (8), 0x4E616d65, 0) AS [Style 0, binary to character];
Hier is het resultatenoverzicht.
Style 0, binary to character
----------------------------
Name
Dit voorbeeld toont aan dat stijl 1 resultaatafkapping kan forceren. De tekens 0x in de resultaatset dwingen de afkorting af.
SELECT CONVERT (CHAR (8), 0x4E616d65, 1) AS [Style 1, binary to character];
Hier is het resultatenoverzicht.
Style 1, binary to character
------------------------------
0x4E616D
Dit voorbeeld laat zien dat Stijl 2 het resultaat niet afkort, omdat het resultaat de karakters 0xniet bevat.
SELECT CONVERT (CHAR (8), 0x4E616d65, 2) AS [Style 2, binary to character];
Hier is het resultatenoverzicht.
Style 2, binary to character
------------------------------
4E616D65
Zet de karakterwaarde Name om naar een binaire waarde.
SELECT CONVERT (BINARY (8), 'Name', 0) AS [Style 0, character to binary];
Hier is het resultatenoverzicht.
Style 0, character to binary
----------------------------
0x4E616D6500000000
SELECT CONVERT (BINARY (4), '0x4E616D65', 1) AS [Style 1, character to binary];
Hier is het resultatenoverzicht.
Style 1, character to binary
----------------------------
0x4E616D65
SELECT CONVERT (BINARY (4), '4E616D65', 2) AS [Style 2, character to binary];
Hier is het resultatenoverzicht.
Style 2, character to binary
----------------------------------
0x4E616D65
Ik. Datum- en tijdgegevenstypen converteren
In dit voorbeeld ziet u de conversie van gegevenstypen datum, tijd en datum/tijd .
DECLARE @d1 AS DATE,
@t1 AS TIME,
@dt1 AS DATETIME;
SET @d1 = GETDATE();
SET @t1 = GETDATE();
SET @dt1 = GETDATE();
SET @d1 = GETDATE();
-- When converting date to datetime the minutes portion becomes zero.
SELECT @d1 AS DATE,
CAST (@d1 AS DATETIME) AS [date as datetime];
-- When converting time to datetime the date portion becomes zero
-- which converts to January 1, 1900.
SELECT @t1 AS TIME,
CAST (@t1 AS DATETIME) AS [time as datetime];
-- When converting datetime to date or time non-applicable portion is dropped.
SELECT @dt1 AS DATETIME,
CAST (@dt1 AS DATE) AS [datetime as date],
CAST (@dt1 AS TIME) AS [datetime as time];
Zorg ervoor dat de waarden zich binnen een compatibel bereik bevinden wanneer u een conversie overweegt van datum tot datum/tijd of datum/tijd2. De minimale jaarwaarde voor datum/tijd is1753, terwijl de minimumjaarwaarde voor 0001 en datum/tijd2 is.
DECLARE @d1 AS DATE,
@dt1 AS DATETIME,
@dt2 AS DATETIME2;
SET @d1 = '1492-08-03';
--This is okay; Minimum YYYY for DATE is 0001
SET @dt2 = CAST (@d1 AS DATETIME2);
--This is okay; Minimum YYYY for DATETIME2 IS 0001
SET @dt1 = CAST (@d1 AS DATETIME);
--This returns an error with (Msg 242) "The conversion of a date data type to a datetime data type resulted in an out-of-range value."
--Minimum YYYY for DATETIME is 1753
J. CONVERTEREN gebruiken met datum/tijd-gegevens in verschillende indelingen
GETDATE() Vanaf waarden wordt in dit voorbeeld gebruikgemaakt CONVERT van alle datum- en tijdstijlen in de sectie Datum- en tijdstijlen van dit artikel.
| Formatteren # | Voorbeeldquery | Voorbeeldresultaat |
|---|---|---|
0 |
SELECT CONVERT(NVARCHAR, GETDATE(), 0) |
23 augustus 2019 13:39 |
1 |
SELECT CONVERT(NVARCHAR, GETDATE(), 1) |
08/23/19 |
2 |
SELECT CONVERT(NVARCHAR, GETDATE(), 2) |
19.08.23 |
3 |
SELECT CONVERT(NVARCHAR, GETDATE(), 3) |
23/08/19 |
4 |
SELECT CONVERT(NVARCHAR, GETDATE(), 4) |
23.08.19 |
5 |
SELECT CONVERT(NVARCHAR, GETDATE(), 5) |
23-08-19 |
6 |
SELECT CONVERT(NVARCHAR, GETDATE(), 6) |
23 aug 19 |
7 |
SELECT CONVERT(NVARCHAR, GETDATE(), 7) |
23 augustus 19 |
8of 24108 |
SELECT CONVERT(NVARCHAR, GETDATE(), 8) |
13:39:17 |
9 of 109 |
SELECT CONVERT(NVARCHAR, GETDATE(), 9) |
23 augustus 2019 1:39:17:090 |
10 |
SELECT CONVERT(NVARCHAR, GETDATE(), 10) |
08-23-19 |
11 |
SELECT CONVERT(NVARCHAR, GETDATE(), 11) |
19/08/23 |
12 |
SELECT CONVERT(NVARCHAR, GETDATE(), 12) |
190823 |
13 of 113 |
SELECT CONVERT(NVARCHAR, GETDATE(), 13) |
23 aug 2019 13:39:17:090 |
14 of 114 |
SELECT CONVERT(NVARCHAR, GETDATE(), 14) |
13:39:17:090 |
20 of 120 |
SELECT CONVERT(NVARCHAR, GETDATE(), 20) |
2019-08-23 13:39:17 |
21of 25121 |
SELECT CONVERT(NVARCHAR, GETDATE(), 21) |
2019-08-23 13:39:17.090 |
22 |
SELECT CONVERT(NVARCHAR, GETDATE(), 22) |
08/23/19 13:39:17 pm |
23 |
SELECT CONVERT(NVARCHAR, GETDATE(), 23) |
2019-08-23 |
101 |
SELECT CONVERT(NVARCHAR, GETDATE(), 101) |
08/23/2019 |
102 |
SELECT CONVERT(NVARCHAR, GETDATE(), 102) |
2019.08.23 |
103 |
SELECT CONVERT(NVARCHAR, GETDATE(), 103) |
23/08/2019 |
104 |
SELECT CONVERT(NVARCHAR, GETDATE(), 104) |
23.08.2019 |
105 |
SELECT CONVERT(NVARCHAR, GETDATE(), 105) |
23-08-2019 |
106 |
SELECT CONVERT(NVARCHAR, GETDATE(), 106) |
23 aug 2019 |
107 |
SELECT CONVERT(NVARCHAR, GETDATE(), 107) |
23 augustus 2019 |
110 |
SELECT CONVERT(NVARCHAR, GETDATE(), 110) |
08-23-2019 |
111 |
SELECT CONVERT(NVARCHAR, GETDATE(), 111) |
2019/08/23 |
112 |
SELECT CONVERT(NVARCHAR, GETDATE(), 112) |
20190823 |
113 |
SELECT CONVERT(NVARCHAR, GETDATE(), 113) |
23 aug 2019 13:39:17.090 |
120 |
SELECT CONVERT(NVARCHAR, GETDATE(), 120) |
2019-08-23 13:39:17 |
121 |
SELECT CONVERT(NVARCHAR, GETDATE(), 121) |
2019-08-23 13:39:17.090 |
126 |
SELECT CONVERT(NVARCHAR, GETDATE(), 126) |
2019-08-23T13:39:17.090 |
127 |
SELECT CONVERT(NVARCHAR, GETDATE(), 127) |
2019-08-23T13:39:17.090 |
130 |
SELECT CONVERT(NVARCHAR, GETDATE(), 130) |
22 ذو الحة 1440 1:39:17.090P |
131 |
SELECT CONVERT(NVARCHAR, GETDATE(), 131) |
22-12-1440 1:39:17.090 |
K. Effecten van prioriteit van gegevenstype in toegestane conversies
Het volgende voorbeeld definieert een variabele van het type varchar(10), wijst een geheel getal toe aan de variabele en selecteert vervolgens een samenvoeging van de variabele met een tekenreeks.
DECLARE @string AS VARCHAR (10);
SET @string = 1;
SELECT @string + ' is a string.' AS Result;
Hier is het resultatenoverzicht.
Result
-----------------------
1 is a string.
De int-waarde van 1 is geconverteerd naar een varchar.
In dit voorbeeld ziet u een vergelijkbare query met behulp van een int-variabele :
DECLARE @notastring AS INT;
SET @notastring = '1';
SELECT @notastring + ' is not a string.' AS Result;
In dit geval genereert de SELECT instructie de volgende fout:
Msg 245, Level 16, State 1, Line 3
Conversion failed when converting the varchar value ' is not a string.' to data type int.
Om de expressie @notastring + ' is not a string.'te evalueren , moet de Database Engine de regels van gegevenstype-precedentie volgen om de impliciete conversie te voltooien voordat het resultaat van de expressie kan worden berekend. Omdat int een hogere prioriteit heeft dan varchar, probeert de Database Engine de string om te zetten naar een geheel getal en faalt omdat deze string niet naar een geheel getal kan worden omgezet.
Als we een string geven die kan worden omgezet, slaagt de uitspraak, zoals te zien is in het volgende voorbeeld:
DECLARE @notastring AS INT;
SET @notastring = '1';
SELECT @notastring + '1';
In dit geval kan de tekenreeks '1' worden geconverteerd naar de gehele waarde 1, zodat deze SELECT instructie de waarde 2retourneert. Wanneer de gegeven datatypes gehele getallen zijn, wordt de + operator een addisionele wiskundige operator in plaats van een stringconcatenatie.
Voorbeelden: Azure Synapse Analytics
L. CAST en CONVERTEREN gebruiken
In dit voorbeeld wordt de naam van het product opgehaald voor de producten met een 3 in het eerste cijfer van de catalogusprijs en worden de ListPrice producten geconverteerd naar int. De database wordt gebruikt AdventureWorksDW2025 .
SELECT EnglishProductName AS ProductName,
ListPrice
FROM dbo.DimProduct
WHERE CAST (ListPrice AS INT) LIKE '3%';
In dit voorbeeld ziet u dezelfde query, CONVERT in plaats van CAST. De database wordt gebruikt AdventureWorksDW2025 .
SELECT EnglishProductName AS ProductName,
ListPrice
FROM dbo.DimProduct
WHERE CONVERT (INT, ListPrice) LIKE '3%';
M. CAST gebruiken met rekenkundige operatoren
In dit voorbeeld wordt één kolomwaarde berekend door de producteenheidsprijs (UnitPrice) te delen door het kortingspercentage (UnitPriceDiscountPct). Dit resultaat wordt vervolgens afgerond op het dichtstbijzijnde gehele getal en ten slotte geconverteerd naar een gegevenstype int . In dit voorbeeld wordt de AdventureWorksDW2025 database gebruikt.
SELECT ProductKey,
UnitPrice,
UnitPriceDiscountPct,
CAST (ROUND(UnitPrice * UnitPriceDiscountPct, 0) AS INT) AS DiscountPrice
FROM dbo.FactResellerSales
WHERE SalesOrderNumber = 'SO47355'
AND UnitPriceDiscountPct > .02;
Hier is het resultatenoverzicht.
ProductKey UnitPrice UnitPriceDiscountPct DiscountPrice
---------- --------- -------------------- -------------
323 430.6445 0.05 22
213 18.5043 0.05 1
456 37.4950 0.10 4
456 37.4950 0.10 4
216 18.5043 0.05 1
N. CAST gebruiken met de LIKE-component
Dit voorbeeld zet de geldkolomListPrice om in een int-type , en vervolgens in een char(20) -type, zodat de LIKE clausule deze kan gebruiken. In dit voorbeeld wordt de AdventureWorksDW2025 database gebruikt.
SELECT EnglishProductName AS Name,
ListPrice
FROM dbo.DimProduct
WHERE CAST (CAST (ListPrice AS INT) AS CHAR (20)) LIKE '2%';
O. CAST en CONVERT gebruiken met datum/tijd-gegevens
In dit voorbeeld worden de huidige datum en tijd weergegeven, gebruikt CAST om de huidige datum en tijd te wijzigen in een gegevenstype teken en wordt CONVERT ten slotte de datum en tijd in de ISO 8601-indeling weergegeven. In dit voorbeeld wordt de AdventureWorksDW2025 database gebruikt.
SELECT TOP (1) SYSDATETIME() AS UnconvertedDateTime,
CAST (SYSDATETIME() AS NVARCHAR (30)) AS UsingCast,
CONVERT (NVARCHAR (30), SYSDATETIME(), 126) AS UsingConvertTo_ISO8601
FROM dbo.DimCustomer;
Hier is het resultatenoverzicht.
UnconvertedDateTime UsingCast UsingConvertTo_ISO8601
--------------------- --------------------------- ---------------------------
07/20/2010 1:44:31 PM 2010-07-20 13:44:31.5879025 2010-07-20T13:44:31.5879025
Dit voorbeeld is het ruwe tegenovergestelde van het vorige voorbeeld. In dit voorbeeld wordt een datum en tijd weergegeven als tekengegevens, wordt gebruikt CAST om de tekengegevens te wijzigen in het gegevenstype datum/tijd en wordt vervolgens gebruikt CONVERT om de tekengegevens te wijzigen in het gegevenstype Datum/tijd . In dit voorbeeld wordt de AdventureWorksDW2025 database gebruikt.
SELECT TOP (1) '2010-07-25T13:50:38.544' AS UnconvertedText,
CAST ('2010-07-25T13:50:38.544' AS DATETIME) AS UsingCast,
CONVERT (DATETIME, '2010-07-25T13:50:38.544', 126) AS UsingConvertFrom_ISO8601
FROM dbo.DimCustomer;
Hier is het resultatenoverzicht.
UnconvertedText UsingCast UsingConvertFrom_ISO8601
----------------------- ----------------------- ------------------------
2010-07-25T13:50:38.544 07/25/2010 1:50:38 PM 07/25/2010 1:50:38 PM