Página 2 de 5

Erro em comandos SQL

Enviado: 07 Out 2015 17:23
por alxsts
Olá!

Aparentemente a sentença SQL está correta. Não entendi
Poka escreveu:É para deixar o campo codcli como not null ( flag = 1)
Se o conteúdo de uma coluna é null e você quer que ele deixe de ser null, é só atribuir um valor para ele, o que você já está fazendo.
Se quiser atribuir null para uma coluna, desde que ela permita, é só fazer

Código: Selecionar todos

SET nome_da_coluna = NULL
Se quiser testar o nome da coluna para ver se é ou não null, uma das opções é

Código: Selecionar todos

WHERE nome_da_coluna IS NULL OR nome_da_coluna_1 IS NOT NULL

Erro em comandos SQL

Enviado: 07 Out 2015 21:59
por Poka
Alexandre

quando eu executo o comando abaixo

Código: Selecionar todos

alter table dadopro add PRIMARY KEY  ( codcli)
dá esse erro

Código: Selecionar todos

Error HY000 - [ODBC Firebird Driver][Firebird]unsuccessful metadata update
Column: CODCLI not defined as NOT NULL - cannot be used in PRIMARY KEY constraint definition
estou entendendo que o campo necessita estar como not null

set tiver + alguma dica , agradeço

Poka

Erro em comandos SQL

Enviado: 08 Out 2015 01:51
por alxsts
Olá!

A sintaxe seria esta:

Código: Selecionar todos

ALTER TABLE dadopro ADD CONSTRAINT PK_dadopro  PRIMARY KEY(codcli);
Se continuar dando este erro que você mostrou, será necessário alterar as propriedades da coluna codcli para NOT NULL e o comando é este mesmo que você mostrou. Não sei qual a razão do erro mas, tente fazer um "quebra galho". Supondo que o tipo de dados da coluna codcli seja BIGINT, crie uma coluna a mais na tabela:

Código: Selecionar todos

ALTER TABLE dadopro ADD tmp_codcli BIGINT NOT NULL;
COMMIT;
O próximo passo será jogar todos os codcli para a nova coluna. Naturalmente, nenhum codcli poderá estar com o valor NULL. Se existir algum NULL nesta coluna, você precisará atribuir um código único e não NULLo para ela, em cada registro que estiver netas condições.
Resolvida a questão dos NULL, preencha a coluna tmp_codcli:

Código: Selecionar todos

UPDATE dadopro SET tmp_codcli = codcli
Se quiser, você poderá mover a nova coluna para a posição 1 da tabela:

Código: Selecionar todos

ALTER TABLE dadopro ALTER tmp_codcli POSITION 1;
Feito isto, tente criar a PK:

Código: Selecionar todos

ALTER TABLE dadopro ADD CONSTRAINT PK_dadopro  PRIMARY KEY(tmp_codcli);
Se der certo delete a coluna codcli antiga

Código: Selecionar todos

ALTER TABLE dadopro drop codcli;
e renomeie a coluna temporária para o nome antigo:

Código: Selecionar todos

ALTER TABLE dadopro alter tmp_codcli to codcli;
Naturalmente, estas operações tem que ser feitas quando o banco não estiver sendo usado por outros usuários. Também é preciso levar em conta as dependências desta tabela, como foreign keys, stored procedures, triggers, views. Nem é preciso dizer que fazer backup da tabela antes é essencial. Para isto, use:

Código: Selecionar todos

SELECT * INTO dadopro_bkp FROM dadoopro;

Erro em comandos SQL

Enviado: 01 Nov 2015 18:05
por Poka
Olá,

Tenho um arquivo de (produto), nesse arquivo não costumo salvar o estoque atual.

Tenho outro arquivo de controle da ficha de estoque (Fichaest) .
Esse arquivo Fichaest contém o movimento de todos os produtos, ele está em ordem de codigo do produto + data, assim
consigo pegar o saldo de qualquer produto, em qualquer data, isto em dbf.
Agora com o Firebird, não estou vendo como pegar esse saldo.

Em dbf eu tinha uma função PegaSaldo(codigo produto, data).
Era só dar um scope , dava um seek numa data maior, retrocedia 1 e estava com o saldo nas mãos.
Não estou vendo jeito de fazer isso com Select.

Imagina o arquivo Fichaest com codigo 10 com lançamentos no mês de dezembro do dia 1 ao dia 31, quero pegar o saldo do dai 15, e no dia 15 tenho varios lançamentos, como fazer num select?

Alguém pode dar alguma idéia?

Poka

Erro em comandos SQL

Enviado: 01 Nov 2015 18:16
por JoséQuintas
Precisa ter alguma ordem.
É selecionar o último lançamento da data.

Dependendo do banco de dados, poderia ser numa destas formas

Código: Selecionar todos

SELECT * FROM ESTMOV WHERE CODIGO=10 AND DATA='2015-11-01' ORDER BY LANCTO DESC LIMIT 1

SELECT TOP 1 * FROM ESTMOV WHERE CODIGO=10 AND DATA='2015-11-01' ORDER BY LANCTO DESC

Erro em comandos SQL

Enviado: 02 Nov 2015 12:40
por Poka
Valeu Quintas.
Vou testar amanhã, se não der certo volto aqui.
O desc matou a charada.

Poka

Erro em comandos SQL

Enviado: 02 Nov 2015 17:00
por Poka
Quintas,
testei agora aqui e deu certo.
Dá certo quando a data que procuro tem lançamento .

Imagina o seguinte na ficha de estoque
no mês de outubro tem movimento do dia 1 ao dia 10 e do dia 20 ao 30.
Para pegar o saldo do dia 15 preciso saber o saldo anterior, que é o saldo do dia 10.

Tem alguma idéia?

Grato

Poka

Erro em comandos SQL

Enviado: 02 Nov 2015 18:00
por Poka
Já consegui resolver.


Poka

Erro em comandos SQL

Enviado: 03 Nov 2015 00:30
por alxsts
Olá!

Muito boa a questão, para quem gosta de desafios SQL. Poderia compartilhar a solução encontrada?

Antes de você informar que havia solucionado, eu estava tentando montar uma solução. Considerando os detalhes do tópico anterior, cheguei na consulta abaixo, considerando que a coluna data seja do tipo DateTime:

Código: Selecionar todos

SELECT * 
  FROM MovEst
 WHERE codigo = 10
   AND data = (SELECT MAX(data) 
                     FROM MovEst
                    WHERE codigo = 10
                      AND Cast(data as Date) <= Cast( '2015-10-15' as Date ) ) 
Nestes casos, ajuda muito informar o layout das tabelas envolvidas. Na tabela MovEst, qual é o tipo de dados da coluna que armazena a data do movimento? Se for um campo que armazena a data e hora, ficará mais fácil. Caso contrário, talvez precise de outra coluna que identifique a sequencia do lançamento, como disse o Quintas.

Erro em comandos SQL

Enviado: 04 Nov 2015 08:35
por Poka
Olá Alexandre,

Obrigado por responder

Realmente um campo de controle de sequencia se faz necessário para pegar o saldo válido

Código: Selecionar todos

func fSaldo(xcodigo,xdata)
    /*
    fb_executa sempre me retorna  a matriz m_select com as linhas recuperadas
   -nControl é o campo de controle que tem 17 digitos, uso uma funcao do firebird
   que me retorna ano,mes,dia,hora,minuto,segundo e fracao de segundo, assim nunca se repete
   formação de nControl  AAAAMMDDHHMMSSFFF
   - fb_data retorna a data no formato correto para teste com o firebird
   */
   local vsaldo:=0 
   //
   str:="select first 1 e.qtdSldAt  from fichaEst e where e.codprod = "+ xcodigo;
   +" and  e.data = '"+fb_data(xdata) +"' order by e.data , nControl desc ;" 
   //
   fb_executa()
   if empty(m_select) 
      // se nao encontrar procuro o saldo anterior
      // pego a data anterior , aqui preciso da data anterior ,  nem sempre a data anterior é o dia  anterior
      str:="select first 1  e.data  from fichaEst e where e.codprod = "+ xcodigo ;    
      +" and  e.data < '"+fb_data(xdata) +"' order by e.data desc ;" 
      fb_executa()
      // se m_select retornar vazio, não tem nenhum lancamento anterior 
      if empty( len(m_select)  )
         vsaldo:=0
      else 
         // pesquiso a data anteriror
	  xdata:=m_select[1,1]
          str:="select first 1 e.qtdSldAt  from fichaEst e where e.codprod = "+ xcodigo;
	  +" and  e.data = '"+fb_data(xdata)	+"' order by e.data , nControl desc ;" 
	   fb_executa()
           vsaldo:=( m_select[1,1])
       endif			
   else
       vsaldo:=( m_select[1,1])
   endif			
retu vsaldo
PROBLEMA

em um relatório com 260 produtos para realizar compras, onde preciso do saldo atual de cada produto, demora cerca de 8 segundos, com dbf era praticamente instantâneo. O meu computador é bem fraco, pode ser que num servidor não venha fazer diferença ( ou notar a diferença). Imagina no select para procurar a data anterior tiver milhares de lançamentosm, em um único produto é instantâneo, agora uma lista com 5 mil produtos!!!.

Vou tentar fazer uns testes com a cláusula Max que você passou para ver se tem jeito também, quem sabe dá alguma diferença.


Poka

Erro em comandos SQL

Enviado: 04 Nov 2015 10:38
por alxsts
Olá.

A tabela do banco tem que ter PK e índice. Poste o script de criação desta tabela.

Erro em comandos SQL

Enviado: 04 Nov 2015 13:21
por JoséQuintas
Como já comentamos por aqui, pra tirar proveito da base de dados em SQL é usar o mínimo possível.
Fazer uma consulta complexa é mais rápido do que fazer várias consultas simples.
Então nesse caso o ideal é um comando que já traga TODOS os cálculos prontos, de TODOS os produtos.

Ainda não cheguei nessa parte no meu aplicativo, mas talvez este post ajude a ter alguma idéia.

https://pctoledo.org/forum/viewto ... 42&t=16136

Erro em comandos SQL

Enviado: 06 Nov 2015 12:06
por Poka
Olá
Fazendo um teste aqui, o arquivo que controla o estoque tem +- 35.000 registros de todos os códigos.
O relatório pega os produtos que tem estoque minimo maior que zero. Dá +- 250 produtos, demora 2 minutos e 40 segundos. Em dbf - de 5 segundos.

Quintas , não vi como consultar tudo de uma só vez nesse caso.
Alexandre veja como está o índice (anexo).

Será que tem jeito de melhorar a performance?


Poka

Erro em comandos SQL

Enviado: 06 Nov 2015 12:19
por alxsts
Olá!

Pode mostrar a consulta SQL que está usando?

Erro em comandos SQL

Enviado: 06 Nov 2015 14:42
por Poka
Mx contém os codigos dos produtos
Msaldo guarda os saldos dos produtos



Código: Selecionar todos

for a:= 1 to len(mx)
  
      msaldo[a]:=fsaldoPa( mx[a,1] ,servData)			

next

Código: Selecionar todos

FUNC FSALDOPA(XCODIGO,XDATA)
			// RETORNA O SALDO DA DATA
			// fb_executa() retorna o resultado na matriz m_select
			LOCAL VSALDO:=0 
			//
			str:="select first 1 e.qtdSldAt from fichapaCI e where e.codprod = "+ xcodigo;
   +" and  e.data = '"+fb_data(xdata)	 +"' order by e.data, e.fb_control desc ;"
			x:=fb_executa()
			*-------------- 
			if empty(m_select) 
   			// se nao encontrar procuro o saldo anterior
   			// pego a data anterior
   			str:="select first 1  e.data  from fichapaCI e where e.codprod = "+ xcodigo ;
						+" and  e.data < '"+fb_data(xdata) +"' order by e.data desc ;" 
   			x:=fb_executa()
   			if empty( len(m_select)  )
						   vsaldo:=0      // nao tem lancamento anterior
						else   
						   xdata:=m_select[1,1]
      			str:="select first 1 e.qtdSldAt  from fichapaCI e where e.codprod = "+ xcodigo ;
									+" and  e.data = '"+fb_data(xdata)		+"' order by e.data , fb_control desc ;" 
		       x:=fb_executa()
      			vsaldo:=( m_select[1,1])
      endif			
   else
   			vsaldo:=( m_select[1,1])
   endif			
			*--------------
   
retu vsaldo

Poka