Antes de publicar un elemento de conexión sobre la falta de documentación sobre esto, ¿alguien confirmará que no me estoy perdiendo algo aquí?
En la página de documentos donde format
aparece como una función de cadena:
"Todas las funciones de cadena incorporadas son deterministas". - Funciones de cadena (Transact-SQL)
Tampoco se menciona format
que no sea determinista en páginas relacionadas:
Sin embargo, al intentar crear una columna calculada persistente:
create table t (date_col date);
insert into t values (getdate());
alter table t add date_formatted_01 as format(date_col,'YYYY') persisted;
Devuelve el siguiente error:
La columna calculada 'date_formatted_01' en la tabla 't' no puede persistir porque la columna no es determinista.
La documentación indica que
Si no se proporciona el argumento de cultura, se usa el idioma de la sesión actual.
pero agregar un argumento cultural no cambia las cosas
Esto también falla
alter table t add date_formatted_02 as format(date_col, 'd', 'en-US' ) persisted
demo de rextester: http://rextester.com/ZMS22966
Demostración dbfiddle.uk: http://dbfiddle.uk/?rdbms=sqlserver_next&fiddle=7fc57d1916e901cb561b551af144aed6
fuente
alter table #t add date_formatted_01 as CONVERT(VARCHAR(20), FORMAT(date_col, 'YYYY', 'en-US')) persisted;
. No estoy seguro de por quéFORMAT
no es determinista, especialmente al especificar la cultura. Ladate_formatted
columna puede serVARCHAR(20)
(aún persistente) y configurarse mediante Trigger usandoFORMAT
. O SQLCLR funciona. Usando la biblioteca SQL # SQLCLR (que escribí), puede hacerloALTER TABLE SQL#.t ADD date_formatted_03 AS SQL#.Date_Format(date_col, 'd', 'en-US') PERSISTED;
(la tabla es propiedad de SQL # ya que el propietario de la tabla y la función deben ser los mismos).Respuestas:
Una función no es necesariamente determinista o no determinista. Hay algunas funciones que pueden ser deterministas según cómo se usen :
CAST
yCONVERT
son tales ejemplos. Según las pruebas que ha realizado hasta ahora, creo que es justo decir queFORMAT
no siempre es determinista, a pesar de ser una función de cadena. Si desea saber si a veces es determinista, la única técnica que se me ocurre es probar suficientes formas diferentes de llamarlo hasta que esté satisfecho. Por ejemplo, consideremosFORMAT
que se aplica a los números. Solo hay diez tipos de entrada numérica diferentes :También parece haber solo nueve formatos numéricos diferentes . Es posible intentar crear columnas persistentes para todas las combinaciones posibles. Algún código para hacerlo está a continuación:
Aquí hay una muestra de la salida:
No pude agregar ninguna de las columnas a la tabla para algunos valores de entrada y culturas. No probé exhaustivamente todas las culturas posibles porque no puedo encontrar una lista de ellas en SQL Server.
Como mínimo, parece seguro concluir que la documentación sobre el determinismo de
FORMAT
es incorrecta, por lo que recomendaría enviar un elemento de conexión para ello.fuente
La
FORMAT
documentación ahora se ha actualizado (en respuesta a su elemento Connect ) para decir:Del mismo modo, las funciones de cadena (Transact-SQL) ahora incluyen:
fuente
No soy un usuario habitual de sqlserver, por lo que podría estar equivocado, pero supongo que el formato no es una función de cadena. De acuerdo con la documentación:
https://docs.microsoft.com/en-us/sql/t-sql/functions/format-transact-sql
formato toma un tipo de fecha o un tipo numérico como argumento. Si todo lo que quiere hacer es tomar la parte del año de una fecha, ¿no puede usar la función de año?
si quieres una representación de cadena:
fuente