SELECT não aceita o comando CASE com ou sem variável global

Utilizo em várias aplicações o comando CASE do MySQL com variáveis globais (ex.: [glo_ano_num]) para identificar qual ano a consulta deverá mostrar.

Isso funcionava normalmente na versão 7.0, mas após atualizar para as versões 7.1 e 8, esse erro começou a ocorrer.

Surge uma mensagem pupup do scriptcase após inserir o CASE no SQL da aplicação, pedindo para que envie o erro à Netmaker.

O interessante que também utilizo o CASE na cláusula WHERE desta mesma consulta, não dá erro e o valor da variável global é retornado, mas o CASE dentro da SELECT não retorna o valor da global [glo_ano_num].

SELECT
id,
codigo_meta_id,
valor_ano1,
valor_ano2,
valor_ano3,
valor_ano4,
CASE [glo_ano_num]
WHEN 1 THEN valor_ano1
WHEN 2 THEN valor_ano2
WHEN 3 THEN valor_ano3
WHEN 4 THEN valor_ano4
END AS valor_ano_aux,
momento_id,
descricao_meta,
descricao_regiao,
codigo_objetivo,
enunciado,
codigo_programa,
titulo_programa,
nome_tiporegiao,
nome_unidade_medida,
sigla_unidade_medida,
codigo_orgao,
nome_orgao,
sigla_orgao,
caracterizacao,
periodo_meta_regionalizada,
execucao_meta,
analise_meta_regionalizada
FROM
view_metas_objetivo_regionalizadas_analise
WHERE codigo_orgao = [glo_unidade] AND momento_id = [glo_momento] AND (periodo_meta_regionalizada = [glo_periodo] OR periodo_meta_regionalizada IS NULL) AND (CASE [glo_ano_num]
when 1 then valor_ano1
when 2 then valor_ano2
when 3 then valor_ano3
when 4 then valor_ano4
END) > 0

Erro na aplicação com debug:

(pdo-mysql): select count(*) from view_metas_objetivo_regionalizadas_analise where codigo_orgao = 30550 AND momento_id = 6 AND (periodo_meta_regionalizada = 25 OR periodo_meta_regionalizada IS NULL) AND (CASE 4 when 1 then valor_ano1 when 2 then valor_ano2 when 3 then valor_ano3 when 4 then valor_ano4 END) > 0

(pdo-mysql): SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valor_ano2, valor_ano3, valor_ano4, nome_unidade_medida, sigla_unidade_medida, CASE [glo_ano_num] WHEN 1 THEN valor_ano1 WHEN 2 THEN valor_ano2 WHEN 3 THEN valor_ano3 WHEN 4 THEN valor_ano4 END as valor_ano_aux, periodo_meta_regionalizada, execucao_meta, analise_meta_regionalizada, codigo_objetivo from view_metas_objetivo_regionalizadas_analise where codigo_orgao = 30550 AND momento_id = 6 AND (periodo_meta_regionalizada = 25 OR periodo_meta_regionalizada IS NULL) AND (CASE 4 when 1 then valor_ano1 when 2 then valor_ano2 when 3 then valor_ano3 when 4 then valor_ano4 END) > 0 order by codigo_orgao asc, codigo_programa asc, codigo_objetivo asc LIMIT 0,17

1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '[glo_ano_num] WHEN 1 THEN valor_ano1 WHEN 2 THEN valor_ano2 ’ at line 1

           ADOConnection._Execute(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valo..., false) % line 1085, file: adodb.inc.php
        ADOConnection.Execute(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valo..., false) % line  222, file: adodb-pdo_mysql.inc.php
     ADODB_pdo_mysql.SelectLimit(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valo..., 17, 0, false, 0) % line  241, file: adodb-pdo.inc.php
  ADODB_pdo.SelectLimit(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valo..., 17, 0) % line  763, file: slide_metas_objetivos_regionalizadas_grid.class.php

slide_metas_objetivos_regionalizadas_grid.inicializa() % line 98, file: slide_metas_objetivos_regionalizadas_grid.class.php
Atenção
Erro ao acessar o banco de dados

SelectLimit(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valor_ano2, valor_ano3, valor_ano4, nome_unidade_medida, sigla_unidade_medida, CASE [glo_ano_num] WHEN 1 THEN valor_ano1 WHEN 2 THEN valor_ano2 WHEN 3 THEN valor_ano3 WHEN 4 THEN valor_ano4 END as valor_ano_aux, periodo_meta_regionalizada, execucao_meta, analise_meta_regionalizada, codigo_objetivo from view_metas_objetivo_regionalizadas_analise where codigo_orgao = 30550 AND momento_id = 6 AND (periodo_meta_regionalizada = 25 OR periodo_meta_regionalizada IS NULL) AND (CASE 4 when 1 then valor_ano1 when 2 then valor_ano2 when 3 then valor_ano3 when 4 then valor_ano4 END) > 0 order by codigo_orgao asc, codigo_programa asc, codigo_objetivo asc, 17, 0)

Faça uma view.

no caso dele não da um view, porque ele ta passando um parámetro, dai na view não tem como …

Sim ele vai ter que refazer ‘toda a lógica deste relatório novamente’, e tentar de outra forma chegar no mesmo resultado, usando uma mistura de views auxiliares com tabelas temporárias.

Olá, tive esse problema e resolvi com IF

tente assim:
IF([glo_ano_num] = 1, valor_ano1,
IF([glo_ano_num] = 2, valor_ano2,
IF([glo_ano_num] = 3, valor_ano3,
IF([glo_ano_num] = 4, valor_ano4,0)))) AS valor_ano_aux

Caro Cleidson,

O problema continua com o IF também.

Na versão 7 isso não acontecia e como muitas consultas que ficou assim após a v7.1 e 8 e será muito complicado corrigir.

O Scriptcase abre um popup de alerta pedindo que reporte o seguinte:

Invalid argument supplied for foreach() | Script: C:\Program Files\NetMake\v81\wwwroot\scriptcase\devel\compat\nm_select_atualiza.php linha: 154]

Acho que isso deverá ser corrigido por se tratar de um BUG da ferramenta ao interpretar o SQL uma vez que o problema continua mesmo substituindo a variável global por um número (1, 2, 3 ou 4).


(pdo-mysql): select count(*) from view_metas_objetivo_regionalizadas_analise where codigo_orgao = 30550 AND momento_id = 6 AND (periodo_meta_regionalizada = 25 OR periodo_meta_regionalizada IS NULL) AND (CASE 3 when 1 then valor_ano1 when 2 then valor_ano2 when 3 then valor_ano3 when 4 then valor_ano4 END) > 0
(pdo-mysql): SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valor_ano2, valor_ano3, valor_ano4, nome_unidade_medida, sigla_unidade_medida, IF([glo_ano_num] = 1,valor_ano1,IF([glo_ano_num] = 2,valor_ano2,IF([glo_ano_num] = 3,valor_ano3,IF([glo_ano_num] = 4,valor_ano4,0)))) as valor_ano_aux, periodo_meta_regionalizada, execucao_meta, analise_meta_regionalizada, codigo_objetivo from view_metas_objetivo_regionalizadas_analise where codigo_orgao = 30550 AND momento_id = 6 AND (periodo_meta_regionalizada = 25 OR periodo_meta_regionalizada IS NULL) AND (CASE 3 when 1 then valor_ano1 when 2 then valor_ano2 when 3 then valor_ano3 when 4 then valor_ano4 END) > 0 order by codigo_orgao asc, codigo_programa asc, codigo_objetivo asc LIMIT 0,17
1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '[glo_ano_num] = 1,valor_ano1,IF([glo_ano_num] = 2,valor_ano2,IF([glo_ano_num] = ’ at line 1
ADOConnection._Execute(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valo…, false) % line 1085, file: adodb.inc.php
ADOConnection.Execute(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valo…, false) % line 222, file: adodb-pdo_mysql.inc.php
ADODB_pdo_mysql.SelectLimit(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valo…, 17, 0, false, 0) % line 241, file: adodb-pdo.inc.php
ADODB_pdo.SelectLimit(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valo…, 17, 0) % line 733, file: slide_metas_objetivos_regionalizadas_teste_grid.class.php
slide_metas_objetivos_regionalizadas_teste_grid.inicializa() % line 98, file: slide_metas_objetivos_regionalizadas_teste_grid.class.php
Atenção
Erro ao acessar o banco de dados

SelectLimit(SELECT codigo_orgao, nome_orgao, codigo_programa, titulo_programa, enunciado, descricao_meta, descricao_regiao, valor_ano1, valor_ano2, valor_ano3, valor_ano4, nome_unidade_medida, sigla_unidade_medida, IF([glo_ano_num] = 1,valor_ano1,IF([glo_ano_num] = 2,valor_ano2,IF([glo_ano_num] = 3,valor_ano3,IF([glo_ano_num] = 4,valor_ano4,0)))) as valor_ano_aux, periodo_meta_regionalizada, execucao_meta, analise_meta_regionalizada, codigo_objetivo from view_metas_objetivo_regionalizadas_analise where codigo_orgao = 30550 AND momento_id = 6 AND (periodo_meta_regionalizada = 25 OR periodo_meta_regionalizada IS NULL) AND (CASE 3 when 1 then valor_ano1 when 2 then valor_ano2 when 3 then valor_ano3 when 4 then valor_ano4 END) > 0 order by codigo_orgao asc, codigo_programa asc, codigo_objetivo asc, 17, 0)

Qual o banco de dados que você está utilizando?

Já tentou configurar a base de dados para acesso assim e usando os ‘IF que o Cleidson passou’.

Eu mesmo e muitos outros desenvolvedores depois que o SC na 7.1 passou a checar a syntax das SQL passamos a fazer VIEW/tmp nas SQL mais complexas.

MySQL

Olá Jailton,

Fiz o sugerido, mas o problema continua.

A sintaxe SQL está correta.

Resolvi assim:

SELECT
id,
codigo_meta_id,
valor_ano1,
valor_ano2,
valor_ano3,
valor_ano4,
0 AS valor_ano_aux,

e em onRecord

IF([glo_ano_num] == 1)
	{
	    {valor_ano_aux} = {valor_ano1};
	}
ELSEIF([glo_ano_num] == 2)
	{
	    {valor_ano_aux} = {valor_ano2};
	}
ELSEIF([glo_ano_num] == 3)
	{
	    {valor_ano_aux} = {valor_ano3};
	}
ELSEIF([glo_ano_num] == 4)
	{
	    {valor_ano_aux} = {valor_ano4};
	}

Poderia ter feito isso criando o campo valor_ano_aux na consulta, mas campos assim não podem ser usados em filtros, quebras, etc… se este não fizer parte da SQL.

Infelizmente não funciona.

O campo “valor_ano_aux” não pode ser usado em quebras, filtros e gráficos pois a SELECT não considera o Aliás do campo e sim o valor 0.

O onRecord é executado após o SELECT e por isso o campo estará sempre vazio/zerado.

Teria que ser com CASE ou IF, mas está com bug pelo fato de o Scriptcase não reconhecer o uso desses comandos SELECT.

paulorr64, você conseguiu resolver o problema?

Olá Cleidson,

Não funciona também com o IF que passou.

Achei que o problema era no teste da sintaxe SQL por usar variável global no CASE, mas ao substituir a global por algum valor válido, acontece o mesmo erro.

Fiz outros testes e o problema é que o Scriptcase não reconhece a variável global como sintaxe do SQL.

Se funcionava nas versões 7 e anteriores, acho que esta solução de verificação da SQL um retrocesso à ferramenta.

Estas opções de verificar ou não a SQL deveria ser de escolha do usuário.

Funcionou substituindo o valor da global depois de refazer a consulta, mas terei que fazer 4 consultas. Uma para cada ano.

Se tenho consultas com até 4 CASE´s, imagina o trabalho que vai dar.

paulorr64, fiz alguns testes aqui e o resultado foi o mesmo que o seu.
Tem uma forma melhor de fazer isso.
Não sei se você conhece sobre PROCEDURE, mas caso não conheça eu te ajudo.

Esses dias tive um problema similar e um colega (Ricardo Sena) me ajudou, então fiz um vídeo mostrando como isso pode ser feito.
https://www.dropbox.com/s/rrzmz8mv8nb7w32/GRID%20COM%20PROCEDURE%20MYSQL.mp4?dl=0

A ideia é a seguinte:
1 - Criar uma tabela auxiliar com a estrutura que você precisa no Banco de Dados
2 - Criar uma Procedure no Banco de Dados, essa Procedure vai ter todo o processo de SELECT e ajustes da tabela auxiliar.
3 - Criar uma Aplicação do Tipo GRID para a tabela auxiliar

No scriptcase, você executa a Procedure que vai receber os parâmetros usando a macro sc_exec_sql(procedure(parametro1, parametro2));

Em seguida chama o GRID relacionado a tabela auxiliar com a macro sc_redir(grid_auxiliar);

Desta forma você poderá usar relatórios tão complexo quanto precisar.

Essa era a tabela ‘tmp’ que eu me referia.

Estou setando uma variável no banco de dados e uso a mesma no lugar da global. Assim evito maior trabalho apenas substituindo.

Obrigado a todos, mas acho que na ultima atualização 8.1.030 isso foi corrigido, pois havia enviado o problema ao suporte.

Podem confirmar?

já tentei com procedure, mas iria me dar muito trabalho para alterar todas as aplicações.

Olá amigos,

Conseguiram uma alternativa para o uso de CASE WHEN no ScriptCase? Minha base é Oracle e também acontece mesma inconsistência.