{"Entry":{"collection":"sql","key":"create-cast","name":"CREATE CAST","aliases":["createcast"],"metadata":{"aliases":["createcast"],"changed_in":["8.0","8.4","9.0","10"],"changes":[{"from":"7.2","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":[],"removed":[]},"status":"added","synopsis":null,"to":"7.3"},{"from":"7.3","purpose_changed":true,"renamed":null,"sections":{"added":["parameters"],"changed":["description","notes","compatibility","see_also"],"removed":[]},"status":"changed","synopsis":null,"to":"7.4"},{"from":"7.4","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes","compatibility"],"removed":[]},"status":"changed","synopsis":{"added":["WITH FUNCTION funcname (argtypes)"],"removed":["WITH FUNCTION funcname (argtype)"]},"to":"8.0"},{"from":"8.0","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["compatibility"],"removed":[]},"status":"changed","synopsis":null,"to":"8.1"},{"from":"8.2","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes","examples"],"removed":[]},"status":"changed","synopsis":null,"to":"8.3"},{"from":"8.3","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes","examples","compatibility"],"removed":[]},"status":"changed","synopsis":{"added":["CREATE CAST (sourcetype AS targettype)","WITH INOUT","[ AS ASSIGNMENT | AS IMPLICIT ]"],"removed":[]},"to":"8.4"},{"from":"8.4","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["parameters"],"removed":[]},"status":"changed","synopsis":{"added":["CREATE CAST (source_type AS target_type)","WITH FUNCTION function_name (argument_type [, ...])","CREATE CAST (source_type AS target_type)","CREATE CAST (source_type AS target_type)"],"removed":["CREATE CAST (sourcetype AS targettype)","WITH FUNCTION funcname (argtypes)","CREATE CAST (sourcetype AS targettype)","CREATE CAST (sourcetype AS targettype)"]},"to":"9.0"},{"from":"9.0","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes"],"removed":[]},"status":"changed","synopsis":null,"to":"9.1"},{"from":"9.1","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters"],"removed":[]},"status":"changed","synopsis":null,"to":"9.2"},{"from":"9.3","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["notes"],"removed":[]},"status":"changed","synopsis":null,"to":"9.4"},{"from":"9.6","purpose_changed":false,"renamed":null,"sections":{"added":[],"changed":["description","parameters","notes"],"removed":[]},"status":"changed","synopsis":{"added":["WITH FUNCTION function_name [ (argument_type [, ...]) ]"],"removed":[]},"to":"10"}],"content_hash":"be13a45d98ec4376f87f01da59656aee912a1d0ba4ded29c64afcf897f4ab0a9","editorial":{},"first_version":"7.3","group":"type","imported_at":"2026-09-30T17:43:37.344141+08:00","last_version":"20","name":"CREATE CAST","object":"CAST","position":3000,"present_in":["7.3","7.4","8.0","8.1","8.2","8.3","8.4","9.0","9.1","9.2","9.3","9.4","9.5","9.6","10","11","12","13","14","15","16","17","18","19","20"],"purpose":"define a new cast","purpose_zh":"","related":["create-function","create-type","drop-cast"],"slug":"create-cast","source_rev":"a709ab85","synopsis":"CREATE CAST (source_type AS target_type)\nWITH FUNCTION function_name [ (argument_type [, ...]) ]\n[ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (source_type AS target_type)\nWITHOUT FUNCTION\n[ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (source_type AS target_type)\nWITH INOUT\n[ AS ASSIGNMENT | AS IMPLICIT ]","verb":"CREATE"}},"Definition":{"Collection":"sql","Key":"create-cast","SourceDatabase":"center","Version":"18","SourceTable":"sqlcmd","SourceKey":"create-cast","SourceRevision":"a709ab85","Facts":{"anchor":"SQL-CREATECAST","file":"sql-createcast.html","lang":"en","name":"CREATE CAST","purpose":"define a new cast","purpose_zh":"","related":["create-function","create-type","drop-cast"],"sections":[{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE CAST\u003c/code\u003e defines a new cast. A cast specifies how to perform a conversion between two data types. For example,\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eSELECT CAST(42 AS float8);\n\u003c/pre\u003e\u003cp\u003econverts the integer constant 42 to type \u003ccode class=\"type\"\u003efloat8\u003c/code\u003e by invoking a previously specified function, in this case \u003ccode class=\"literal\"\u003efloat8(int4)\u003c/code\u003e. (If no suitable cast has been defined, the conversion fails.)\u003c/p\u003e\u003cp\u003eTwo types can be \u003cem class=\"firstterm\"\u003ebinary coercible\u003c/em\u003e, which means that the conversion can be performed \u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003efor free\u003c/span\u003e”\u003c/span\u003e without invoking any function. This requires that corresponding values use the same internal representation. For instance, the types \u003ccode class=\"type\"\u003etext\u003c/code\u003e and \u003ccode class=\"type\"\u003evarchar\u003c/code\u003e are binary coercible both ways. Binary coercibility is not necessarily a symmetric relationship. For example, the cast from \u003ccode class=\"type\"\u003exml\u003c/code\u003e to \u003ccode class=\"type\"\u003etext\u003c/code\u003e can be performed for free in the present implementation, but the reverse direction requires a function that performs at least a syntax check. (Two types that are binary coercible both ways are also referred to as binary compatible.)\u003c/p\u003e\u003cp\u003eYou can define a cast as an \u003cem class=\"firstterm\"\u003eI/O conversion cast\u003c/em\u003e by using the \u003ccode class=\"literal\"\u003eWITH INOUT\u003c/code\u003e syntax. An I/O conversion cast is performed by invoking the output function of the source data type, and passing the resulting string to the input function of the target data type. In many common cases, this feature avoids the need to write a separate cast function for conversion. An I/O conversion cast acts the same as a regular function-based cast; only the implementation is different.\u003c/p\u003e\u003cp\u003eBy default, a cast can be invoked only by an explicit cast request, that is an explicit \u003ccode class=\"literal\"\u003eCAST(\u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e AS \u003cem class=\"replaceable\"\u003e\u003ccode\u003etypename\u003c/code\u003e\u003c/em\u003e)\u003c/code\u003e or \u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e\u003ccode class=\"literal\"\u003e::\u003c/code\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etypename\u003c/code\u003e\u003c/em\u003e construct.\u003c/p\u003e\u003cp\u003eIf the cast is marked \u003ccode class=\"literal\"\u003eAS ASSIGNMENT\u003c/code\u003e then it can be invoked implicitly when assigning a value to a column of the target data type. For example, supposing that \u003ccode class=\"literal\"\u003efoo.f1\u003c/code\u003e is a column of type \u003ccode class=\"type\"\u003etext\u003c/code\u003e, then:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eINSERT INTO foo (f1) VALUES (42);\n\u003c/pre\u003e\u003cp\u003ewill be allowed if the cast from type \u003ccode class=\"type\"\u003einteger\u003c/code\u003e to type \u003ccode class=\"type\"\u003etext\u003c/code\u003e is marked \u003ccode class=\"literal\"\u003eAS ASSIGNMENT\u003c/code\u003e, otherwise not. (We generally use the term \u003cem class=\"firstterm\"\u003eassignment cast\u003c/em\u003e to describe this kind of cast.)\u003c/p\u003e\u003cp\u003eIf the cast is marked \u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e then it can be invoked implicitly in any context, whether assignment or internally in an expression. (We generally use the term \u003cem class=\"firstterm\"\u003eimplicit cast\u003c/em\u003e to describe this kind of cast.) For example, consider this query:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eSELECT 2 + 4.0;\n\u003c/pre\u003e\u003cp\u003eThe parser initially marks the constants as being of type \u003ccode class=\"type\"\u003einteger\u003c/code\u003e and \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e respectively. There is no \u003ccode class=\"type\"\u003einteger\u003c/code\u003e \u003ccode class=\"literal\"\u003e+\u003c/code\u003e \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e operator in the system catalogs, but there is a \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e \u003ccode class=\"literal\"\u003e+\u003c/code\u003e \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e operator. The query will therefore succeed if a cast from \u003ccode class=\"type\"\u003einteger\u003c/code\u003e to \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e is available and is marked \u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e — which in fact it is. The parser will apply the implicit cast and resolve the query as if it had been written\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eSELECT CAST ( 2 AS numeric ) + 4.0;\n\u003c/pre\u003e\u003cp\u003eNow, the catalogs also provide a cast from \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e to \u003ccode class=\"type\"\u003einteger\u003c/code\u003e. If that cast were marked \u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e — which it is not — then the parser would be faced with choosing between the above interpretation and the alternative of casting the \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e constant to \u003ccode class=\"type\"\u003einteger\u003c/code\u003e and applying the \u003ccode class=\"type\"\u003einteger\u003c/code\u003e \u003ccode class=\"literal\"\u003e+\u003c/code\u003e \u003ccode class=\"type\"\u003einteger\u003c/code\u003e operator. Lacking any knowledge of which choice to prefer, it would give up and declare the query ambiguous. The fact that only one of the two casts is implicit is the way in which we teach the parser to prefer resolution of a mixed \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e-and-\u003ccode class=\"type\"\u003einteger\u003c/code\u003e expression as \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e; there is no built-in knowledge about that.\u003c/p\u003e\u003cp\u003eIt is wise to be conservative about marking casts as implicit. An overabundance of implicit casting paths can cause \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e to choose surprising interpretations of commands, or to be unable to resolve commands at all because there are multiple possible interpretations. A good rule of thumb is to make a cast implicitly invokable only for information-preserving transformations between types in the same general type category. For example, the cast from \u003ccode class=\"type\"\u003eint2\u003c/code\u003e to \u003ccode class=\"type\"\u003eint4\u003c/code\u003e can reasonably be implicit, but the cast from \u003ccode class=\"type\"\u003efloat8\u003c/code\u003e to \u003ccode class=\"type\"\u003eint4\u003c/code\u003e should probably be assignment-only. Cross-type-category casts, such as \u003ccode class=\"type\"\u003etext\u003c/code\u003e to \u003ccode class=\"type\"\u003eint4\u003c/code\u003e, are best made explicit-only.\u003c/p\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003eNote\u003c/h3\u003e\u003cp\u003eSometimes it is necessary for usability or standards-compliance reasons to provide multiple implicit casts among a set of types, resulting in ambiguity that cannot be avoided as above. The parser has a fallback heuristic based on \u003cem class=\"firstterm\"\u003etype categories\u003c/em\u003e and \u003cem class=\"firstterm\"\u003epreferred types\u003c/em\u003e that can help to provide desired behavior in such cases. See \u003ca href=\"/docs/18/sql-createtype.html\" title=\"CREATE TYPE\"\u003e\u003cspan class=\"refentrytitle\"\u003eCREATE TYPE\u003c/span\u003e\u003c/a\u003e for more information.\u003c/p\u003e\u003c/div\u003e\u003cp\u003eTo be able to create a cast, you must own the source or the target data type and have \u003ccode class=\"literal\"\u003eUSAGE\u003c/code\u003e privilege on the other type. To create a binary-coercible cast, you must be superuser. (This restriction is made because an erroneous binary-coercible cast conversion can easily crash the server.)\u003c/p\u003e","key":"description","title":"Description"},{"html":"\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003esource_type\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of the source data type of the cast.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etarget_type\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe name of the target data type of the cast.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003efunction_name\u003c/code\u003e\u003c/em\u003e[(\u003cem class=\"replaceable\"\u003e\u003ccode\u003eargument_type\u003c/code\u003e\u003c/em\u003e [, ...])]\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eThe function used to perform the cast. The function name can be schema-qualified. If it is not, the function will be looked up in the schema search path. The function's result data type must match the target type of the cast. Its arguments are discussed below. If no argument list is specified, the function name must be unique in its schema.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eWITHOUT FUNCTION\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eIndicates that the source type is binary-coercible to the target type, so no function is required to perform the cast.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eWITH INOUT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eIndicates that the cast is an I/O conversion cast, performed by invoking the output function of the source data type, and passing the resulting string to the input function of the target data type.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eAS ASSIGNMENT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eIndicates that the cast can be invoked implicitly in assignment contexts.\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003eIndicates that the cast can be invoked implicitly in any context.\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003eCast implementation functions can have one to three arguments. The first argument type must be identical to or binary-coercible from the cast's source type. The second argument, if present, must be type \u003ccode class=\"type\"\u003einteger\u003c/code\u003e; it receives the type modifier associated with the destination type, or \u003ccode class=\"literal\"\u003e-1\u003c/code\u003e if there is none. The third argument, if present, must be type \u003ccode class=\"type\"\u003eboolean\u003c/code\u003e; it receives \u003ccode class=\"literal\"\u003etrue\u003c/code\u003e if the cast is an explicit cast, \u003ccode class=\"literal\"\u003efalse\u003c/code\u003e otherwise. (Bizarrely, the SQL standard demands different behaviors for explicit and implicit casts in some cases. This argument is supplied for functions that must implement such casts. It is not recommended that you design your own data types so that this matters.)\u003c/p\u003e\u003cp\u003eThe return type of a cast function must be identical to or binary-coercible to the cast's target type.\u003c/p\u003e\u003cp\u003eOrdinarily a cast must have different source and target data types. However, it is allowed to declare a cast with identical source and target types if it has a cast implementation function with more than one argument. This is used to represent type-specific length coercion functions in the system catalogs. The named function is used to coerce a value of the type to the type modifier value given by its second argument.\u003c/p\u003e\u003cp\u003eWhen a cast has different source and target types and a function that takes more than one argument, it supports converting from one type to another and applying a length coercion in a single step. When no such entry is available, coercion to a type that uses a type modifier involves two cast steps, one to convert between data types and a second to apply the modifier.\u003c/p\u003e\u003cp\u003eA cast to or from a domain type currently has no effect. Casting to or from a domain uses the casts associated with its underlying type.\u003c/p\u003e","key":"parameters","title":"Parameters"},{"html":"\u003cp\u003eUse \u003ca href=\"/docs/18/sql-dropcast.html\" title=\"DROP CAST\"\u003e\u003ccode class=\"command\"\u003eDROP CAST\u003c/code\u003e\u003c/a\u003e to remove user-defined casts.\u003c/p\u003e\u003cp\u003eRemember that if you want to be able to convert types both ways you need to declare casts both ways explicitly.\u003c/p\u003e\u003cp\u003eIt is normally not necessary to create casts between user-defined types and the standard string types (\u003ccode class=\"type\"\u003etext\u003c/code\u003e, \u003ccode class=\"type\"\u003evarchar\u003c/code\u003e, and \u003ccode class=\"type\"\u003echar(\u003cem class=\"replaceable\"\u003e\u003ccode\u003en\u003c/code\u003e\u003c/em\u003e)\u003c/code\u003e, as well as user-defined types that are defined to be in the string category). \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e provides automatic I/O conversion casts for that. The automatic casts to string types are treated as assignment casts, while the automatic casts from string types are explicit-only. You can override this behavior by declaring your own cast to replace an automatic cast, but usually the only reason to do so is if you want the conversion to be more easily invokable than the standard assignment-only or explicit-only setting. Another possible reason is that you want the conversion to behave differently from the type's I/O function; but that is sufficiently surprising that you should think twice about whether it's a good idea. (A small number of the built-in types do indeed have different behaviors for conversions, mostly because of requirements of the SQL standard.)\u003c/p\u003e\u003cp\u003eWhile not required, it is recommended that you continue to follow this old convention of naming cast implementation functions after the target data type. Many users are used to being able to cast data types using a function-style notation, that is \u003cem class=\"replaceable\"\u003e\u003ccode\u003etypename\u003c/code\u003e\u003c/em\u003e(\u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e). This notation is in fact nothing more nor less than a call of the cast implementation function; it is not specially treated as a cast. If your conversion functions are not named to support this convention then you will have surprised users. Since \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e allows overloading of the same function name with different argument types, there is no difficulty in having multiple conversion functions from different types that all use the target type's name.\u003c/p\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003eNote\u003c/h3\u003e\u003cp\u003eActually the preceding paragraph is an oversimplification: there are two cases in which a function-call construct will be treated as a cast request without having matched it to an actual function. If a function call \u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e(\u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e) does not exactly match any existing function, but \u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e is the name of a data type and \u003ccode class=\"structname\"\u003epg_cast\u003c/code\u003e provides a binary-coercible cast to this type from the type of \u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e, then the call will be construed as a binary-coercible cast. This exception is made so that binary-coercible casts can be invoked using functional syntax, even though they lack any function. Likewise, if there is no \u003ccode class=\"structname\"\u003epg_cast\u003c/code\u003e entry but the cast would be to or from a string type, the call will be construed as an I/O conversion cast. This exception allows I/O conversion casts to be invoked using functional syntax.\u003c/p\u003e\u003c/div\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003eNote\u003c/h3\u003e\u003cp\u003eThere is also an exception to the exception: I/O conversion casts from composite types to string types cannot be invoked using functional syntax, but must be written in explicit cast syntax (either \u003ccode class=\"literal\"\u003eCAST\u003c/code\u003e or \u003ccode class=\"literal\"\u003e::\u003c/code\u003e notation). This exception was added because after the introduction of automatically-provided I/O conversion casts, it was found too easy to accidentally invoke such a cast when a function or column reference was intended.\u003c/p\u003e\u003c/div\u003e","key":"notes","title":"Notes"},{"html":"\u003cp\u003eTo create an assignment cast from type \u003ccode class=\"type\"\u003ebigint\u003c/code\u003e to type \u003ccode class=\"type\"\u003eint4\u003c/code\u003e using the function \u003ccode class=\"literal\"\u003eint4(bigint)\u003c/code\u003e:\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;\n\u003c/pre\u003e\u003cp\u003e(This cast is already predefined in the system.)\u003c/p\u003e","key":"examples","title":"Examples"},{"html":"\u003cp\u003eThe \u003ccode class=\"command\"\u003eCREATE CAST\u003c/code\u003e command conforms to the \u003cacronym\u003eSQL\u003c/acronym\u003e standard, except that SQL does not make provisions for binary-coercible types or extra arguments to implementation functions. \u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e is a \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e extension, too.\u003c/p\u003e","key":"compatibility","title":"Compatibility"},{"html":"\u003cp\u003e\u003ca href=\"/wiki/sql/create-function/?v=18\" title=\"CREATE FUNCTION\"\u003e\u003cspan class=\"refentrytitle\"\u003eCREATE FUNCTION\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/create-type/?v=18\" title=\"CREATE TYPE\"\u003e\u003cspan class=\"refentrytitle\"\u003eCREATE TYPE\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/drop-cast/?v=18\" title=\"DROP CAST\"\u003e\u003cspan class=\"refentrytitle\"\u003eDROP CAST\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e","key":"see_also","title":"See Also"}],"sections_same_as":"","slug":"18","synopsis_html":"CREATE CAST (\u003cem class=\"replaceable\"\u003e\u003ccode\u003esource_type\u003c/code\u003e\u003c/em\u003e AS \u003cem class=\"replaceable\"\u003e\u003ccode\u003etarget_type\u003c/code\u003e\u003c/em\u003e)\n    WITH FUNCTION \u003cem class=\"replaceable\"\u003e\u003ccode\u003efunction_name\u003c/code\u003e\u003c/em\u003e [ (\u003cem class=\"replaceable\"\u003e\u003ccode\u003eargument_type\u003c/code\u003e\u003c/em\u003e [, ...]) ]\n    [ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (\u003cem class=\"replaceable\"\u003e\u003ccode\u003esource_type\u003c/code\u003e\u003c/em\u003e AS \u003cem class=\"replaceable\"\u003e\u003ccode\u003etarget_type\u003c/code\u003e\u003c/em\u003e)\n    WITHOUT FUNCTION\n    [ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (\u003cem class=\"replaceable\"\u003e\u003ccode\u003esource_type\u003c/code\u003e\u003c/em\u003e AS \u003cem class=\"replaceable\"\u003e\u003ccode\u003etarget_type\u003c/code\u003e\u003c/em\u003e)\n    WITH INOUT\n    [ AS ASSIGNMENT | AS IMPLICIT ]","synopsis_text":"CREATE CAST (source_type AS target_type)\nWITH FUNCTION function_name [ (argument_type [, ...]) ]\n[ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (source_type AS target_type)\nWITHOUT FUNCTION\n[ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (source_type AS target_type)\nWITH INOUT\n[ AS ASSIGNMENT | AS IMPLICIT ]"},"ManualEvidence":{},"MeasuredEvidence":{}},"Text":{"Collection":"sql","Key":"create-cast","SourceDatabase":"pgweb","Version":"18","Locale":"zh-Hans","Title":"CREATE CAST","Summary":"定义一种新的类型转换","BodyHTML":"\u003cpre\u003eCREATE CAST (source_type AS target_type)\nWITH FUNCTION function_name [ (argument_type [, ...]) ]\n[ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (source_type AS target_type)\nWITHOUT FUNCTION\n[ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (source_type AS target_type)\nWITH INOUT\n[ AS ASSIGNMENT | AS IMPLICIT ]\u003c/pre\u003e\u003csection\u003e\u003ch2\u003e描述\u003c/h2\u003e\u003cp\u003e\u003ccode\u003eCREATE CAST\u003c/code\u003e定义一种新的类型转换。类型转换规定如何在两种数据类型之间执行转换。例如，\u003c/p\u003e\u003cpre\u003eSELECT CAST(42 AS float8);\n\u003c/pre\u003e\u003cp\u003e通过调用一个预先指定的函数（此处是 \u003ccode\u003efloat8(int4)\u003c/code\u003e）把整型常量 42 转换成 \u003ccode\u003efloat8\u003c/code\u003e类型。（如果没有定义合适的类型转换，转换就会失败。）\u003c/p\u003e\u003cp\u003e两种类型可以是\u003cem\u003e二进制可强制转换\u003c/em\u003e的，这意味着无需调用任何函数，就可以\u003cspan\u003e“\u003cspan\u003e免费\u003c/span\u003e”\u003c/span\u003e执行转换。这要求对应的值使用相同的内部表示。例如，\u003ccode\u003etext\u003c/code\u003e和\u003ccode\u003evarchar\u003c/code\u003e这两种类型在两个方向上都是二进制可强制转换的。二进制可强制转换性不一定是对称关系。例如，在当前实现中，从\u003ccode\u003exml\u003c/code\u003e到\u003ccode\u003etext\u003c/code\u003e的类型转换可以免费执行，但反方向则需要一个至少执行语法检查的函数。（双向都二进制可强制转换的两种类型也称为二进制兼容。）\u003c/p\u003e\u003cp\u003e使用\u003ccode\u003eWITH INOUT\u003c/code\u003e语法，你可以把一种类型转换定义为\u003cem\u003e基于 I/O 的类型转换\u003c/em\u003e。基于 I/O 的类型转换通过调用源数据类型的输出函数，并将得到的字符串传给目标数据类型的输入函数来执行。在许多常见情况下，这项特性免去了为转换单独编写类型转换函数的必要。基于 I/O 的类型转换与常规的基于函数的类型转换行为相同，只是实现方式不同。\u003c/p\u003e\u003cp\u003e默认情况下，只有显式请求类型转换时才会调用一种类型转换，也就是显式使用\u003ccode\u003eCAST(\u003cem\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e AS \u003cem\u003e\u003ccode\u003etypename\u003c/code\u003e\u003c/em\u003e)\u003c/code\u003e或 \u003cem\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e\u003ccode\u003e::\u003c/code\u003e\u003cem\u003e\u003ccode\u003etypename\u003c/code\u003e\u003c/em\u003e 这种构造。\u003c/p\u003e\u003cp\u003e如果一种类型转换被标记为\u003ccode\u003eAS ASSIGNMENT\u003c/code\u003e，那么在把值赋给目标数据类型的列时就可以隐式调用它。例如，假设\u003ccode\u003efoo.f1\u003c/code\u003e 是一个\u003ccode\u003etext\u003c/code\u003e类型的列，那么如果从\u003ccode\u003einteger\u003c/code\u003e到 \u003ccode\u003etext\u003c/code\u003e的类型转换被标记为\u003ccode\u003eAS ASSIGNMENT\u003c/code\u003e，则：\u003c/p\u003e\u003cpre\u003eINSERT INTO foo (f1) VALUES (42);\n\u003c/pre\u003e\u003cp\u003e就会被允许，否则不会。（我们通常用术语\u003cem\u003e赋值类型转换\u003c/em\u003e来描述这种类型转换。）\u003c/p\u003e\u003cp\u003e如果一种类型转换被标记为\u003ccode\u003eAS IMPLICIT\u003c/code\u003e，那么无论是在赋值上下文中还是在表达式内部，都可以在任何上下文中隐式调用它。（我们通常用术语\u003cem\u003e隐式类型转换\u003c/em\u003e来描述这种类型转换。）例如，考虑这个查询：\u003c/p\u003e\u003cpre\u003eSELECT 2 + 4.0;\n\u003c/pre\u003e\u003cp\u003e解析器最初分别把这两个常量标记为\u003ccode\u003einteger\u003c/code\u003e和 \u003ccode\u003enumeric\u003c/code\u003e类型。系统目录中没有\u003ccode\u003einteger\u003c/code\u003e \u003ccode\u003e+\u003c/code\u003e \u003ccode\u003enumeric\u003c/code\u003e操作符，但有一个 \u003ccode\u003enumeric\u003c/code\u003e \u003ccode\u003e+\u003c/code\u003e \u003ccode\u003enumeric\u003c/code\u003e操作符。因此，如果存在一种从\u003ccode\u003einteger\u003c/code\u003e到\u003ccode\u003enumeric\u003c/code\u003e的可用类型转换，并且被标记为\u003ccode\u003eAS IMPLICIT\u003c/code\u003e — 实际上确实如此 — 该查询就会成功。解析器将应用该隐式类型转换，并把该查询当作写成了如下形式来解析：\u003c/p\u003e\u003cpre\u003eSELECT CAST ( 2 AS numeric ) + 4.0;\n\u003c/pre\u003e\u003cp\u003e现在，系统目录还提供了一种从\u003ccode\u003enumeric\u003c/code\u003e到\u003ccode\u003einteger\u003c/code\u003e的类型转换。如果该类型转换被标记为\u003ccode\u003eAS IMPLICIT\u003c/code\u003e — 实际上并没有 — 那么解析器就必须在上面的解释方式和另一种方案之间作出选择：把\u003ccode\u003enumeric\u003c/code\u003e常量转换成\u003ccode\u003einteger\u003c/code\u003e，然后应用 \u003ccode\u003einteger\u003c/code\u003e \u003ccode\u003e+\u003c/code\u003e \u003ccode\u003einteger\u003c/code\u003e操作符。由于它不知道该偏向哪一种选择，就会放弃并将该查询判定为有歧义。两种类型转换中只有一种是隐式的，正是借此我们让解析器倾向于把混合了 \u003ccode\u003enumeric\u003c/code\u003e和\u003ccode\u003einteger\u003c/code\u003e的表达式解析为 \u003ccode\u003enumeric\u003c/code\u003e；系统对此并没有内置知识。\u003c/p\u003e\u003cp\u003e把类型转换标记为隐式时应当保持保守。过多的隐式类型转换路径可能导致 \u003cspan\u003ePostgreSQL\u003c/span\u003e对命令作出令人意外的解释，或者因为存在多种可能的解释而根本无法解析命令。一个好的经验法则是，只有对同一一般类型分类中且能保留信息的类型间转换，才让它可以被隐式调用。例如，从\u003ccode\u003eint2\u003c/code\u003e到\u003ccode\u003eint4\u003c/code\u003e的类型转换可以合理地设为隐式，但从\u003ccode\u003efloat8\u003c/code\u003e到\u003ccode\u003eint4\u003c/code\u003e的类型转换大概应仅限赋值使用。跨类型分类的类型转换，例如从\u003ccode\u003etext\u003c/code\u003e到\u003ccode\u003eint4\u003c/code\u003e，最好只允许显式调用。\u003c/p\u003e\u003cdiv\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e有时出于可用性或标准兼容性的原因，有必要在一组类型之间提供多种隐式类型转换，这会带来无法用上述方式避免的歧义。解析器有一种基于\u003cem\u003e类型分类\u003c/em\u003e和\u003cem\u003e首选类型\u003c/em\u003e的后备启发式规则，在这种情况下有助于提供期望的行为。详见\u003ca href=\"/docs/18/sql-createtype.html\" title=\"CREATE TYPE\" rel=\"nofollow\"\u003e\u003cspan\u003eCREATE TYPE\u003c/span\u003e\u003c/a\u003e。\u003c/p\u003e\u003c/div\u003e\u003cp\u003e要能够创建一种类型转换，你必须拥有源数据类型或目标数据类型之一，并且对另一种类型具有\u003ccode\u003eUSAGE\u003c/code\u003e权限。要创建一种二进制强制转换，你必须是超级用户。（之所以有这一限制，是因为错误的二进制强制转换很容易使服务器崩溃。）\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e参数\u003c/h2\u003e\u003cdiv\u003e\u003cdl\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003esource_type\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该类型转换的源数据类型的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003cem\u003e\u003ccode\u003etarget_type\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该类型转换的目标数据类型的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003e\u003cem\u003e\u003ccode\u003efunction_name\u003c/code\u003e\u003c/em\u003e[(\u003cem\u003e\u003ccode\u003eargument_type\u003c/code\u003e\u003c/em\u003e [, ...])]\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e用于执行该类型转换的函数。函数名可以用模式限定；如果没有，则会在模式搜索路径中查找该函数。该函数的结果数据类型必须与类型转换的目标类型一致。其参数见下文。如果没有指定参数列表，则该函数名在其模式中必须是唯一的。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eWITHOUT FUNCTION\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示源类型对目标类型是二进制可强制转换的，因此执行该类型转换不需要函数。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eWITH INOUT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示该类型转换是一种基于 I/O 的类型转换，其执行方式是调用源数据类型的输出函数，并将得到的字符串传给目标数据类型的输入函数。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eAS ASSIGNMENT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示该类型转换可以在赋值上下文中隐式调用。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan\u003e\u003ccode\u003eAS IMPLICIT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示该类型转换可以在任何上下文中隐式调用。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003e类型转换实现函数可以有一到三个参数。第一个参数类型必须与源类型相同，或者可以由源类型进行二进制强制转换得到。第二个参数（如果有）必须是 \u003ccode\u003einteger\u003c/code\u003e类型；它接收与目标类型关联的类型修饰符，如果没有则为\u003ccode\u003e-1\u003c/code\u003e。第三个参数（如果有）必须是\u003ccode\u003eboolean\u003c/code\u003e 类型；如果该类型转换是显式类型转换，它接收\u003ccode\u003etrue\u003c/code\u003e，否则接收\u003ccode\u003efalse\u003c/code\u003e。（奇怪的是，SQL 标准在某些情况下要求显式类型转换和隐式类型转换具有不同的行为。这个参数是为必须实现这类类型转换的函数提供的。不建议你把自己的数据类型设计成需要关心这一点。）\u003c/p\u003e\u003cp\u003e类型转换函数的返回类型必须与类型转换的目标类型相同，或者对该目标类型是二进制可强制转换的。\u003c/p\u003e\u003cp\u003e通常，类型转换的源数据类型和目标数据类型必须不同。不过，如果它具有一个接受多个参数的类型转换实现函数，则允许声明源类型和目标类型相同的类型转换。这用于在系统目录中表示特定类型的长度强制函数。所命名的函数用于将该类型的值强制为其第二个参数给定的类型修饰符值。\u003c/p\u003e\u003cp\u003e当一种类型转换的源类型和目标类型不同，且其函数接受多个参数时，它支持在一个步骤中同时完成从一种类型到另一种类型的转换并应用长度强制。如果没有这样的条目，对使用类型修饰符的类型进行强制就需要两个类型转换步骤：先在数据类型之间进行转换，再应用该修饰符。\u003c/p\u003e\u003cp\u003e当前，到域类型或从域类型的类型转换都没有效果。到域或从域的类型转换都会使用与其底层类型关联的类型转换。\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e注解\u003c/h2\u003e\u003cp\u003e使用\u003ca href=\"/docs/18/sql-dropcast.html\" title=\"DROP CAST\" rel=\"nofollow\"\u003e\u003ccode\u003eDROP CAST\u003c/code\u003e\u003c/a\u003e移除用户定义的类型转换。\u003c/p\u003e\u003cp\u003e请记住，如果你希望能够双向转换类型，就需要在两个方向上分别显式声明类型转换。\u003c/p\u003e\u003cp\u003e通常没有必要在用户定义类型与标准字符串类型（\u003ccode\u003etext\u003c/code\u003e、\u003ccode\u003evarchar\u003c/code\u003e和\u003ccode\u003echar(\u003cem\u003e\u003ccode\u003en\u003c/code\u003e\u003c/em\u003e)\u003c/code\u003e，以及被定义为属于字符串分类的用户定义类型）之间创建类型转换。\u003cspan\u003ePostgreSQL\u003c/span\u003e会自动为此提供基于 I/O 的类型转换。转换到字符串类型的自动类型转换被视为赋值类型转换，而从字符串类型出发的自动类型转换则只允许显式调用。你可以声明自己的类型转换来替代自动类型转换，从而覆盖这种行为，但通常这样做的唯一原因，是希望该转换比标准的仅赋值或仅显式设置更容易调用。另一种可能的原因是，你希望该转换的行为不同于该类型的 I/O 函数；但这已经足够反常，你应该三思这是不是一个好主意。（确实有少数内置类型在转换行为上有所不同，大多是由于 SQL 标准的要求。）\u003c/p\u003e\u003cp\u003e虽然这不是强制要求，但仍建议你继续遵循这种老惯例，即按目标数据类型为类型转换实现函数命名。许多用户已经习惯于用函数风格的记法进行类型转换，也就是\u003cem\u003e\u003ccode\u003etypename\u003c/code\u003e\u003c/em\u003e(\u003cem\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e)。这种记法实际上无非就是调用类型转换实现函数；它不会被特别当作类型转换处理。如果你的转换函数没有按这种惯例命名，那么用户会感到意外。由于 \u003cspan\u003ePostgreSQL\u003c/span\u003e允许同一函数名按不同参数类型重载，因此让来自不同类型的多个转换函数都使用目标类型的名称并不存在困难。\u003c/p\u003e\u003cdiv\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e实际上，前一段说得过于简单了：有两种情况下，即使一个函数调用形式没有匹配到实际存在的函数，也会被当作类型转换请求。如果函数调用 \u003cem\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e(\u003cem\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e)不能与任何现有函数精确匹配，但\u003cem\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e是一个数据类型名，并且 \u003ccode\u003epg_cast\u003c/code\u003e为从\u003cem\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e的类型到该类型提供了二进制强制转换，那么该调用会被解释为二进制强制转换。作出这一例外，是为了让二进制强制转换即使没有任何函数，也能使用函数语法调用。同样，如果没有\u003ccode\u003epg_cast\u003c/code\u003e项，但该类型转换的目标或源是字符串类型，则该调用会被解释为基于 I/O 的类型转换。这一例外允许基于 I/O 的类型转换使用函数语法调用。\u003c/p\u003e\u003c/div\u003e\u003cdiv\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e还有一个例外中的例外：从复合类型到字符串类型的基于 I/O 的类型转换不能使用函数语法调用，而必须写成显式类型转换语法（\u003ccode\u003eCAST\u003c/code\u003e 或\u003ccode\u003e::\u003c/code\u003e记法）。增加这一例外，是因为在引入自动提供的基于 I/O 的类型转换之后，如果原意是函数调用或列引用，就太容易意外地触发这种类型转换了。\u003c/p\u003e\u003c/div\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e示例\u003c/h2\u003e\u003cp\u003e要使用函数\u003ccode\u003eint4(bigint)\u003c/code\u003e创建一种从类型 \u003ccode\u003ebigint\u003c/code\u003e到类型\u003ccode\u003eint4\u003c/code\u003e的赋值类型转换：\u003c/p\u003e\u003cpre\u003eCREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;\n\u003c/pre\u003e\u003cp\u003e（在系统中这种类型转换已经被预定义。）\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e兼容性\u003c/h2\u003e\u003cp\u003e\u003ccode\u003eCREATE CAST\u003c/code\u003e命令符合\u003cacronym\u003eSQL\u003c/acronym\u003e标准，不过 SQL 没有对二进制可强制转换的类型或实现函数的额外参数作出规定。\u003ccode\u003eAS IMPLICIT\u003c/code\u003e也是 \u003cspan\u003ePostgreSQL\u003c/span\u003e的扩展。\u003c/p\u003e\u003c/section\u003e\u003csection\u003e\u003ch2\u003e另见\u003c/h2\u003e\u003cp\u003e\u003ca href=\"/wiki/sql/create-function/?v=18\" title=\"CREATE FUNCTION\" rel=\"nofollow\"\u003e\u003cspan\u003eCREATE FUNCTION\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/create-type/?v=18\" title=\"CREATE TYPE\" rel=\"nofollow\"\u003e\u003cspan\u003eCREATE TYPE\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/drop-cast/?v=18\" title=\"DROP CAST\" rel=\"nofollow\"\u003e\u003cspan\u003eDROP CAST\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e\u003c/section\u003e","SourceRevision":"1b5ca64c","ContentHash":"529f60bbf784ee9ad94bfbfc8d418996b5d5b2e4432b4f41782a4201440fb5f4","Payload":{"purpose_zh":"定义一种新的类型转换","sections":[{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE CAST\u003c/code\u003e定义一种新的类型转换。类型转换规定如何在两种数据类型之间执行转换。例如，\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eSELECT CAST(42 AS float8);\n\u003c/pre\u003e\u003cp\u003e通过调用一个预先指定的函数（此处是 \u003ccode class=\"literal\"\u003efloat8(int4)\u003c/code\u003e）把整型常量 42 转换成 \u003ccode class=\"type\"\u003efloat8\u003c/code\u003e类型。（如果没有定义合适的类型转换，转换就会失败。）\u003c/p\u003e\u003cp\u003e两种类型可以是\u003cem class=\"firstterm\"\u003e二进制可强制转换\u003c/em\u003e的，这意味着无需调用任何函数，就可以\u003cspan class=\"quote\"\u003e“\u003cspan class=\"quote\"\u003e免费\u003c/span\u003e”\u003c/span\u003e执行转换。这要求对应的值使用相同的内部表示。例如，\u003ccode class=\"type\"\u003etext\u003c/code\u003e和\u003ccode class=\"type\"\u003evarchar\u003c/code\u003e这两种类型在两个方向上都是二进制可强制转换的。二进制可强制转换性不一定是对称关系。例如，在当前实现中，从\u003ccode class=\"type\"\u003exml\u003c/code\u003e到\u003ccode class=\"type\"\u003etext\u003c/code\u003e的类型转换可以免费执行，但反方向则需要一个至少执行语法检查的函数。（双向都二进制可强制转换的两种类型也称为二进制兼容。）\u003c/p\u003e\u003cp\u003e使用\u003ccode class=\"literal\"\u003eWITH INOUT\u003c/code\u003e语法，你可以把一种类型转换定义为\u003cem class=\"firstterm\"\u003e基于 I/O 的类型转换\u003c/em\u003e。基于 I/O 的类型转换通过调用源数据类型的输出函数，并将得到的字符串传给目标数据类型的输入函数来执行。在许多常见情况下，这项特性免去了为转换单独编写类型转换函数的必要。基于 I/O 的类型转换与常规的基于函数的类型转换行为相同，只是实现方式不同。\u003c/p\u003e\u003cp\u003e默认情况下，只有显式请求类型转换时才会调用一种类型转换，也就是显式使用\u003ccode class=\"literal\"\u003eCAST(\u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e AS \u003cem class=\"replaceable\"\u003e\u003ccode\u003etypename\u003c/code\u003e\u003c/em\u003e)\u003c/code\u003e或 \u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e\u003ccode class=\"literal\"\u003e::\u003c/code\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etypename\u003c/code\u003e\u003c/em\u003e 这种构造。\u003c/p\u003e\u003cp\u003e如果一种类型转换被标记为\u003ccode class=\"literal\"\u003eAS ASSIGNMENT\u003c/code\u003e，那么在把值赋给目标数据类型的列时就可以隐式调用它。例如，假设\u003ccode class=\"literal\"\u003efoo.f1\u003c/code\u003e 是一个\u003ccode class=\"type\"\u003etext\u003c/code\u003e类型的列，那么如果从\u003ccode class=\"type\"\u003einteger\u003c/code\u003e到 \u003ccode class=\"type\"\u003etext\u003c/code\u003e的类型转换被标记为\u003ccode class=\"literal\"\u003eAS ASSIGNMENT\u003c/code\u003e，则：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eINSERT INTO foo (f1) VALUES (42);\n\u003c/pre\u003e\u003cp\u003e就会被允许，否则不会。（我们通常用术语\u003cem class=\"firstterm\"\u003e赋值类型转换\u003c/em\u003e来描述这种类型转换。）\u003c/p\u003e\u003cp\u003e如果一种类型转换被标记为\u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e，那么无论是在赋值上下文中还是在表达式内部，都可以在任何上下文中隐式调用它。（我们通常用术语\u003cem class=\"firstterm\"\u003e隐式类型转换\u003c/em\u003e来描述这种类型转换。）例如，考虑这个查询：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eSELECT 2 + 4.0;\n\u003c/pre\u003e\u003cp\u003e解析器最初分别把这两个常量标记为\u003ccode class=\"type\"\u003einteger\u003c/code\u003e和 \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e类型。系统目录中没有\u003ccode class=\"type\"\u003einteger\u003c/code\u003e \u003ccode class=\"literal\"\u003e+\u003c/code\u003e \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e操作符，但有一个 \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e \u003ccode class=\"literal\"\u003e+\u003c/code\u003e \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e操作符。因此，如果存在一种从\u003ccode class=\"type\"\u003einteger\u003c/code\u003e到\u003ccode class=\"type\"\u003enumeric\u003c/code\u003e的可用类型转换，并且被标记为\u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e — 实际上确实如此 — 该查询就会成功。解析器将应用该隐式类型转换，并把该查询当作写成了如下形式来解析：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eSELECT CAST ( 2 AS numeric ) + 4.0;\n\u003c/pre\u003e\u003cp\u003e现在，系统目录还提供了一种从\u003ccode class=\"type\"\u003enumeric\u003c/code\u003e到\u003ccode class=\"type\"\u003einteger\u003c/code\u003e的类型转换。如果该类型转换被标记为\u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e — 实际上并没有 — 那么解析器就必须在上面的解释方式和另一种方案之间作出选择：把\u003ccode class=\"type\"\u003enumeric\u003c/code\u003e常量转换成\u003ccode class=\"type\"\u003einteger\u003c/code\u003e，然后应用 \u003ccode class=\"type\"\u003einteger\u003c/code\u003e \u003ccode class=\"literal\"\u003e+\u003c/code\u003e \u003ccode class=\"type\"\u003einteger\u003c/code\u003e操作符。由于它不知道该偏向哪一种选择，就会放弃并将该查询判定为有歧义。两种类型转换中只有一种是隐式的，正是借此我们让解析器倾向于把混合了 \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e和\u003ccode class=\"type\"\u003einteger\u003c/code\u003e的表达式解析为 \u003ccode class=\"type\"\u003enumeric\u003c/code\u003e；系统对此并没有内置知识。\u003c/p\u003e\u003cp\u003e把类型转换标记为隐式时应当保持保守。过多的隐式类型转换路径可能导致 \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e对命令作出令人意外的解释，或者因为存在多种可能的解释而根本无法解析命令。一个好的经验法则是，只有对同一一般类型分类中且能保留信息的类型间转换，才让它可以被隐式调用。例如，从\u003ccode class=\"type\"\u003eint2\u003c/code\u003e到\u003ccode class=\"type\"\u003eint4\u003c/code\u003e的类型转换可以合理地设为隐式，但从\u003ccode class=\"type\"\u003efloat8\u003c/code\u003e到\u003ccode class=\"type\"\u003eint4\u003c/code\u003e的类型转换大概应仅限赋值使用。跨类型分类的类型转换，例如从\u003ccode class=\"type\"\u003etext\u003c/code\u003e到\u003ccode class=\"type\"\u003eint4\u003c/code\u003e，最好只允许显式调用。\u003c/p\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e有时出于可用性或标准兼容性的原因，有必要在一组类型之间提供多种隐式类型转换，这会带来无法用上述方式避免的歧义。解析器有一种基于\u003cem class=\"firstterm\"\u003e类型分类\u003c/em\u003e和\u003cem class=\"firstterm\"\u003e首选类型\u003c/em\u003e的后备启发式规则，在这种情况下有助于提供期望的行为。详见\u003ca href=\"/docs/18/sql-createtype.html\" title=\"CREATE TYPE\"\u003e\u003cspan class=\"refentrytitle\"\u003eCREATE TYPE\u003c/span\u003e\u003c/a\u003e。\u003c/p\u003e\u003c/div\u003e\u003cp\u003e要能够创建一种类型转换，你必须拥有源数据类型或目标数据类型之一，并且对另一种类型具有\u003ccode class=\"literal\"\u003eUSAGE\u003c/code\u003e权限。要创建一种二进制强制转换，你必须是超级用户。（之所以有这一限制，是因为错误的二进制强制转换很容易使服务器崩溃。）\u003c/p\u003e","key":"description","title":"描述"},{"html":"\u003cdiv class=\"variablelist\"\u003e\u003cdl class=\"variablelist\"\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003esource_type\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该类型转换的源数据类型的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003etarget_type\u003c/code\u003e\u003c/em\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e该类型转换的目标数据类型的名称。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003e\u003cem class=\"replaceable\"\u003e\u003ccode\u003efunction_name\u003c/code\u003e\u003c/em\u003e[(\u003cem class=\"replaceable\"\u003e\u003ccode\u003eargument_type\u003c/code\u003e\u003c/em\u003e [, ...])]\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e用于执行该类型转换的函数。函数名可以用模式限定；如果没有，则会在模式搜索路径中查找该函数。该函数的结果数据类型必须与类型转换的目标类型一致。其参数见下文。如果没有指定参数列表，则该函数名在其模式中必须是唯一的。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eWITHOUT FUNCTION\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示源类型对目标类型是二进制可强制转换的，因此执行该类型转换不需要函数。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eWITH INOUT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示该类型转换是一种基于 I/O 的类型转换，其执行方式是调用源数据类型的输出函数，并将得到的字符串传给目标数据类型的输入函数。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eAS ASSIGNMENT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示该类型转换可以在赋值上下文中隐式调用。\u003c/p\u003e\u003c/dd\u003e\u003cdt\u003e\u003cspan class=\"term\"\u003e\u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e\u003c/span\u003e\u003c/dt\u003e\u003cdd\u003e\u003cp\u003e表示该类型转换可以在任何上下文中隐式调用。\u003c/p\u003e\u003c/dd\u003e\u003c/dl\u003e\u003c/div\u003e\u003cp\u003e类型转换实现函数可以有一到三个参数。第一个参数类型必须与源类型相同，或者可以由源类型进行二进制强制转换得到。第二个参数（如果有）必须是 \u003ccode class=\"type\"\u003einteger\u003c/code\u003e类型；它接收与目标类型关联的类型修饰符，如果没有则为\u003ccode class=\"literal\"\u003e-1\u003c/code\u003e。第三个参数（如果有）必须是\u003ccode class=\"type\"\u003eboolean\u003c/code\u003e 类型；如果该类型转换是显式类型转换，它接收\u003ccode class=\"literal\"\u003etrue\u003c/code\u003e，否则接收\u003ccode class=\"literal\"\u003efalse\u003c/code\u003e。（奇怪的是，SQL 标准在某些情况下要求显式类型转换和隐式类型转换具有不同的行为。这个参数是为必须实现这类类型转换的函数提供的。不建议你把自己的数据类型设计成需要关心这一点。）\u003c/p\u003e\u003cp\u003e类型转换函数的返回类型必须与类型转换的目标类型相同，或者对该目标类型是二进制可强制转换的。\u003c/p\u003e\u003cp\u003e通常，类型转换的源数据类型和目标数据类型必须不同。不过，如果它具有一个接受多个参数的类型转换实现函数，则允许声明源类型和目标类型相同的类型转换。这用于在系统目录中表示特定类型的长度强制函数。所命名的函数用于将该类型的值强制为其第二个参数给定的类型修饰符值。\u003c/p\u003e\u003cp\u003e当一种类型转换的源类型和目标类型不同，且其函数接受多个参数时，它支持在一个步骤中同时完成从一种类型到另一种类型的转换并应用长度强制。如果没有这样的条目，对使用类型修饰符的类型进行强制就需要两个类型转换步骤：先在数据类型之间进行转换，再应用该修饰符。\u003c/p\u003e\u003cp\u003e当前，到域类型或从域类型的类型转换都没有效果。到域或从域的类型转换都会使用与其底层类型关联的类型转换。\u003c/p\u003e","key":"parameters","title":"参数"},{"html":"\u003cp\u003e使用\u003ca href=\"/docs/18/sql-dropcast.html\" title=\"DROP CAST\"\u003e\u003ccode class=\"command\"\u003eDROP CAST\u003c/code\u003e\u003c/a\u003e移除用户定义的类型转换。\u003c/p\u003e\u003cp\u003e请记住，如果你希望能够双向转换类型，就需要在两个方向上分别显式声明类型转换。\u003c/p\u003e\u003cp\u003e通常没有必要在用户定义类型与标准字符串类型（\u003ccode class=\"type\"\u003etext\u003c/code\u003e、\u003ccode class=\"type\"\u003evarchar\u003c/code\u003e和\u003ccode class=\"type\"\u003echar(\u003cem class=\"replaceable\"\u003e\u003ccode\u003en\u003c/code\u003e\u003c/em\u003e)\u003c/code\u003e，以及被定义为属于字符串分类的用户定义类型）之间创建类型转换。\u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e会自动为此提供基于 I/O 的类型转换。转换到字符串类型的自动类型转换被视为赋值类型转换，而从字符串类型出发的自动类型转换则只允许显式调用。你可以声明自己的类型转换来替代自动类型转换，从而覆盖这种行为，但通常这样做的唯一原因，是希望该转换比标准的仅赋值或仅显式设置更容易调用。另一种可能的原因是，你希望该转换的行为不同于该类型的 I/O 函数；但这已经足够反常，你应该三思这是不是一个好主意。（确实有少数内置类型在转换行为上有所不同，大多是由于 SQL 标准的要求。）\u003c/p\u003e\u003cp\u003e虽然这不是强制要求，但仍建议你继续遵循这种老惯例，即按目标数据类型为类型转换实现函数命名。许多用户已经习惯于用函数风格的记法进行类型转换，也就是\u003cem class=\"replaceable\"\u003e\u003ccode\u003etypename\u003c/code\u003e\u003c/em\u003e(\u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e)。这种记法实际上无非就是调用类型转换实现函数；它不会被特别当作类型转换处理。如果你的转换函数没有按这种惯例命名，那么用户会感到意外。由于 \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e允许同一函数名按不同参数类型重载，因此让来自不同类型的多个转换函数都使用目标类型的名称并不存在困难。\u003c/p\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e实际上，前一段说得过于简单了：有两种情况下，即使一个函数调用形式没有匹配到实际存在的函数，也会被当作类型转换请求。如果函数调用 \u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e(\u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e)不能与任何现有函数精确匹配，但\u003cem class=\"replaceable\"\u003e\u003ccode\u003ename\u003c/code\u003e\u003c/em\u003e是一个数据类型名，并且 \u003ccode class=\"structname\"\u003epg_cast\u003c/code\u003e为从\u003cem class=\"replaceable\"\u003e\u003ccode\u003ex\u003c/code\u003e\u003c/em\u003e的类型到该类型提供了二进制强制转换，那么该调用会被解释为二进制强制转换。作出这一例外，是为了让二进制强制转换即使没有任何函数，也能使用函数语法调用。同样，如果没有\u003ccode class=\"structname\"\u003epg_cast\u003c/code\u003e项，但该类型转换的目标或源是字符串类型，则该调用会被解释为基于 I/O 的类型转换。这一例外允许基于 I/O 的类型转换使用函数语法调用。\u003c/p\u003e\u003c/div\u003e\u003cdiv class=\"note\"\u003e\u003ch3\u003e注意\u003c/h3\u003e\u003cp\u003e还有一个例外中的例外：从复合类型到字符串类型的基于 I/O 的类型转换不能使用函数语法调用，而必须写成显式类型转换语法（\u003ccode class=\"literal\"\u003eCAST\u003c/code\u003e 或\u003ccode class=\"literal\"\u003e::\u003c/code\u003e记法）。增加这一例外，是因为在引入自动提供的基于 I/O 的类型转换之后，如果原意是函数调用或列引用，就太容易意外地触发这种类型转换了。\u003c/p\u003e\u003c/div\u003e","key":"notes","title":"注解"},{"html":"\u003cp\u003e要使用函数\u003ccode class=\"literal\"\u003eint4(bigint)\u003c/code\u003e创建一种从类型 \u003ccode class=\"type\"\u003ebigint\u003c/code\u003e到类型\u003ccode class=\"type\"\u003eint4\u003c/code\u003e的赋值类型转换：\u003c/p\u003e\u003cpre class=\"programlisting\"\u003eCREATE CAST (bigint AS int4) WITH FUNCTION int4(bigint) AS ASSIGNMENT;\n\u003c/pre\u003e\u003cp\u003e（在系统中这种类型转换已经被预定义。）\u003c/p\u003e","key":"examples","title":"示例"},{"html":"\u003cp\u003e\u003ccode class=\"command\"\u003eCREATE CAST\u003c/code\u003e命令符合\u003cacronym\u003eSQL\u003c/acronym\u003e标准，不过 SQL 没有对二进制可强制转换的类型或实现函数的额外参数作出规定。\u003ccode class=\"literal\"\u003eAS IMPLICIT\u003c/code\u003e也是 \u003cspan class=\"productname\"\u003ePostgreSQL\u003c/span\u003e的扩展。\u003c/p\u003e","key":"compatibility","title":"兼容性"},{"html":"\u003cp\u003e\u003ca href=\"/wiki/sql/create-function/?v=18\" title=\"CREATE FUNCTION\"\u003e\u003cspan class=\"refentrytitle\"\u003eCREATE FUNCTION\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/create-type/?v=18\" title=\"CREATE TYPE\"\u003e\u003cspan class=\"refentrytitle\"\u003eCREATE TYPE\u003c/span\u003e\u003c/a\u003e, \u003ca href=\"/wiki/sql/drop-cast/?v=18\" title=\"DROP CAST\"\u003e\u003cspan class=\"refentrytitle\"\u003eDROP CAST\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e","key":"see_also","title":"另见"}],"sections_same_as":"","synopsis_html":"CREATE CAST (\u003cem class=\"replaceable\"\u003e\u003ccode\u003esource_type\u003c/code\u003e\u003c/em\u003e AS \u003cem class=\"replaceable\"\u003e\u003ccode\u003etarget_type\u003c/code\u003e\u003c/em\u003e)\n    WITH FUNCTION \u003cem class=\"replaceable\"\u003e\u003ccode\u003efunction_name\u003c/code\u003e\u003c/em\u003e [ (\u003cem class=\"replaceable\"\u003e\u003ccode\u003eargument_type\u003c/code\u003e\u003c/em\u003e [, ...]) ]\n    [ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (\u003cem class=\"replaceable\"\u003e\u003ccode\u003esource_type\u003c/code\u003e\u003c/em\u003e AS \u003cem class=\"replaceable\"\u003e\u003ccode\u003etarget_type\u003c/code\u003e\u003c/em\u003e)\n    WITHOUT FUNCTION\n    [ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (\u003cem class=\"replaceable\"\u003e\u003ccode\u003esource_type\u003c/code\u003e\u003c/em\u003e AS \u003cem class=\"replaceable\"\u003e\u003ccode\u003etarget_type\u003c/code\u003e\u003c/em\u003e)\n    WITH INOUT\n    [ AS ASSIGNMENT | AS IMPLICIT ]","synopsis_text":"CREATE CAST (source_type AS target_type)\nWITH FUNCTION function_name [ (argument_type [, ...]) ]\n[ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (source_type AS target_type)\nWITHOUT FUNCTION\n[ AS ASSIGNMENT | AS IMPLICIT ]\n\nCREATE CAST (source_type AS target_type)\nWITH INOUT\n[ AS ASSIGNMENT | AS IMPLICIT ]"}},"RequestedLocale":"zh-Hans","Fallback":false,"Versions":["10","11","12","13","14","15","16","17","18","19","20","7.3","7.4","8.0","8.1","8.2","8.3","8.4","9.0","9.1","9.2","9.3","9.4","9.5","9.6"],"Locales":["en","zh-Hans"],"Signatures":null,"Spellings":null,"SQLState":null,"Evidence":null}
