Access 2003 SQL Switch quebra tipos de dados?
-
20-09-2019 - |
Pergunta
Estou executando o Access 2003. Estou usando o Switch para selecionar campos de data com base em um critério booleano:
Switch(<criterion>, Date1, 1, Date2)
isto é, se "critério" for verdadeiro, retornar a data1, caso contrário, retorne a data2.
Date1 e Date2 são colunas de data/hora em uma tabela.
O problema é que o Switch os retorna como texto - não data/hora!
Existe uma maneira de forçá-los a ser encontrados? eu tentei
Switch(<criterion>, #Date1#, 1, #Date2#)
E
Switch(<criterion>, Val(Date1), 1, Val(Date2))
Ambos falham com uma mensagem de erro ou outra.
Alguma ideia?
Solução
Eu acho que a função imediata se [iif ()] é uma correspondência melhor para o que você está tentando fazer:
IIf(<criterion>, Date1, Date2)
Mas a função Switch () não deve quebrar os tipos de dados e não é incompatível com os tipos de dados de data/hora. Considere esta função:
Public Function trySwitch(ByVal pWhichDay As String) As Variant
Dim varOut As Variant
varOut = Switch(pWhichDay = "yesterday", Date - 1, _
pWhichDay = "today", Date, _
pWhichDay = "tomorrow", Date + 1)
trySwitch = varOut
End Function
Tryswitch ("Today") retorna 10/6/2009 e Typename (Tryswitch ("Today")) retorna Encontro
Outras dicas
Há algo estranho com o seu exemplo.
O Switch aceita pares de expressão e, se o primeiro avaliar como verdadeiro, seu valor emparelhado será retornado, caso contrário, ele passa para o segundo e avalia esse argumento.
Você parece estar tratando 1 como verdadeiro, o que é porque não é Fales, mas você estaria melhor com:
Switch(<criterion>, Date1, True, Date2)
Mas isso é apenas uma replicação da funcionalidade da função imediata, iif () e iif (), leva menos argumentos.
Mas tem o mesmo problema, na medida em que retorna uma variante. Mas você deve ser capaz de coagir isso para um tipo de dados que pode ser formatado como uma data.
Mas se essa variante será implicitamente coagida ou você precisará fazê -lo explicitamente, depende de onde você está usando. Em um resultado de consulta, você pode classificar a saída do IIF ([Critério], Date1, Date2) como uma data, porque a coluna é coagida até o tipo de data.
Se você precisar fazer a coerção explicitamente, o CDATE () é a função de usar - você envolve a função externa que produz saída variante com a função cdate () para ter certeza de que a saída variante é explicitamente coagida até o momento modelo:
CDate(IIf(<criterion>, Date1, Date2))
Mas posso muito bem estar perdendo algo importante aqui, pois pareço estar em uma faixa completamente diferente ...
Você pode postar algum código e dados para reproduzir o problema, por favor? Como isso é SWITCH()
No código SQL, então eu acho que o SQL DDL (CREATE TABLE
etc) e DML (INSERT INTO
para adicionar dados) seria mais apropriado :)
PICKY PONTO: O ACCESS DATABASE SQL não possui um tipo de dados 'booleano'. Tem um YESNO
tipo de dados que pode ser o NULL
valor; A lógica de três valores não é booleana.
Aqui estão alguns SQL DML (Modo de consulta ANSI-92 sintaxe) para demonstrar como funciona como esperado para mim:
SELECT TYPENAME
(
SWITCH
(
NULL, #2009-01-01 00:00:00#,
FALSE, #2009-06-15 12:00:00#,
TRUE, #2009-12-31 23:59:59#
)
);
Altere qualquer um dos valores do 'critério' e o valor é sempre retornado como 'data', ou seja, do tipo DATETIME
.
ATUALIZAR:
Este
TYPENAME
A função é uma ótima ferramenta ... o acesso parece interpretar toda a "coluna" do resultado do resultado de maneira diferente
De fato. Porque uma coluna pode ser apenas um tipo de dados os resultados de TYPENAME()
Na fila pode ser enganosa. Os valores de linha dos tipos mistos devem ser 'promovidos' para um tipo de dados mais alto. Como é habitual com o mecanismo de banco de dados de acesso, o processo é totalmente opaco e a documentação sobre o assunto completamente ausente, então você só precisa sugar e ver por exemplo
SELECT #2009-01-01 00:00:00# AS row_value,
TYPENAME(#2009-01-01 00:00:00#) AS row_type
FROM Customers
UNION ALL
SELECT 0.5,
TYPENAME(0.5) AS row_type
FROM Customers
Retornos 'data' e 'decimal', respectivamente, mas qual será a coluna? Aparentemente, a resposta é:
SELECT DT1.row_value, TYPENAME(DT1.row_value) AS column_type
FROM (
SELECT DISTINCT #2009-01-01 00:00:00# AS row_value
FROM Customers
UNION ALL
SELECT DISTINCT 0.5
FROM Customers
) AS DT1;
'Corda'?!
... O que, obviamente, nem nem é um tipo de dados SQL de mecanismo de banco de dados de acesso. Então TYPENAME()
, irritantemente, usa o nome do tipo 'melhor ajuste' VBA. Por exemplo:
SELECT TYPENAME(CBOOL(0));
Retorna 'Boolean', embora, como discutido acima, não existe um tipo de dados booleano no SQL do mecanismo de banco de dados de acesso. E
SELECT TYPENAME(my_binary_col)
retorna 'string'. Observe a mesma limitação de mapeamento VBA se aplica ao CAST
funções (ainda outro aborrecimento), por exemplo, não há 'elenco para BINARY
'função e o CDEC()
A função permanece quebrada desde o jet 4.0 :(