prezados,
tenho um formulario mestre/detalhe onde no mestre são inseridos os dados referente a um pedido e no detalhe os itens do pedido
tentei com a opção de auto incremento mas observei que o numero salvo no campo reflete todos os registro que estão no banco
gostaria que fosse inserido em um determinado campo a sequencia dos itens tipo 1, 2, 3 e por ai vai é possivel?
Vamos supor, que você tenha estes campos:
Mestre: PedidoID
Detalhe: PedidoID, Item
Com isso vamos gerar uma sequência para os Itens.
No OnLoad do Mestre (Pai) Coloque:
[glo_PedidoID]={PedidoID}; // Marcar como Variável Global de saída em Aplicação > Variáveis Globais
No Detalhe > Filho
no SQL WHERE coloque
PedidoID = [glo_PedidoID];
No OnLoad do Detalhe > Filho colocar:
{PedidoID} = [glo_PedidoID];
Nas Linhas do detalhe selecione adicione o Campo: PedidoID e Item na Linha, marque o campo PedidoID como Campo escondido.
Crie em Métodos > PHP Novo = GerarSequencia, coloque este Código:
// ** Adaptar o nome dos campos a suas tabelas...
if (empty({Item})) {
/* Macro sc_lookup */
$sql="
SELECT
MAX(Item)+1
FROM
pedidos_itens
WHERE
PedidoID = [glo_PedidoID]
ORDER BY
PedidoID, Item
";
sc_lookup(chk_item, $sql);
/* Erro no lookup */
if (FALSE === {chk_item}) {
sc_error_message("Ocorreu um erro no acesso ao banco de dados.<BR>");
}
elseif (empty({chk_item})) { /* EOF */
// sc_error_message("Nenhum valor foi retornado pelo banco.<BR>");
}
else {
/* Inclua aqui sua rotina de processamento */
{Item}={chk_item[0][0]};
}
}
if (empty({Item}) {
{Item}=1;
}
Criar um EventoAjax > Item > OnFocus:
GerarSequencia();
No Evento OnValidate:
GerarSequencia();
obrigado pela dica Jailton
primeiro
Mestre: no caso do mestre tenho 2 chaves primarias
Detalhe: tenho as 2 chaves primarias e um campo auto incremento
como seria no caso do OnLoad?
Eu, particularmente,
utilizo Trigger direto no banco, para fazer este tipo de auto-numeração secundária.
opa outra dica! agradeço se compartilhar a ideia
É só adicionar o segundo campo da Chave Primária Composta, em tudo.
Vamos supor, que você tenha estes campos na Chave Primária Composta:
Mestre: PedidoID, CaixaID
Detalhe: PedidoID, CaixaID, Item
Com isso vamos gerar uma sequência para os Itens.
No OnLoad do Mestre (Pai) Coloque:
[glo_PedidoID]={PedidoID}; // Marcar como Variável Global de saída em Aplicação > Variáveis Globais
[glo_CaixaID]={CaixaID}; // Marcar como Variável Global de saída em Aplicação > Variáveis Globais
No Detalhe > Filho
no SQL WHERE coloque
PedidoID = [glo_PedidoID] AND CaixaID = [glo_CaixaID]
No OnLoad do Detalhe > Filho colocar:
{PedidoID} = [glo_PedidoID];
{CaixaID} = [glo_CaixaID];
Nas Linhas do detalhe selecione adicione o Campo: PedidoID, CaixaID e Item na Linha, marque o campo PedidoID e CaixaID como Campo escondido.
Mas o recomendado para modelagem de Banco de Dados atualmente é um campo só auto incremento como chave primária, e as outras chaves que precisar pode controlar como chave Única, etc.
https://ericlemes.com/2009/11/11/bd-idsechavescompostas/
Criando uma única ID por tabela como chave primária fica depois tudo mais fácil para relacionar elas, criar links, urls, passar parâmetros, etc.
// ** Adaptar o nome dos campos a suas tabelas...
if (empty({Item})) {
/* Macro sc_lookup */
$sql="
SELECT
MAX(Item)+1
FROM
pedidos_itens
WHERE
PedidoID = [glo_PedidoID] AND CaixaID = [glo_CaixaID]
ORDER BY
PedidoID, CaixaID, Item
";
sc_lookup(chk_item, $sql);
/* Erro no lookup */
if (FALSE === {chk_item}) {
sc_error_message("Ocorreu um erro no acesso ao banco de dados.<BR>");
}
elseif (empty({chk_item})) { /* EOF */
// sc_error_message("Nenhum valor foi retornado pelo banco.<BR>");
}
else {
/* Inclua aqui sua rotina de processamento */
{Item}={chk_item[0][0]};
}
}
if (empty({Item}) {
{Item}=1;
}
Eu:
Criar campo integer sequencial nos itens do pedido
Stored Procedure renumeraItens (int idMestre) <- executar no onafterDelete
Lê os itens do pedido do primeiro ao último e Update no Sequencial
Trigger Before Insert na tabela itens de pedido:
new.sequencial = select max(sequencial) + 1 from pedido_itens where idPedido = new.idPedido;
Algo parecido.
Particularmente não adoto PK composta. PK para mim sempre ID Interger AutoIncrement.
Exato,
Não é um boa pratica usar PKs compostas, utilize sempre FKs (foreign key) compostas.
estou fechando o topico
obrigado por todas as soluções, ajustei a ideia do Jailton (obrigado) no entanto estou estudando as outras opções e quanto ao uso das FK
estou fechando o topico
obrigado por todas as soluções, ajustei a ideia do Jailton (obrigado) no entanto estou estudando as outras opções e quanto ao uso das FK
A nível de estudo, tenho mais essas 2 formas de fazer uma pelo SC, que re-ordena os no. dos Itens e uma por procedure, que faz a mesma coisa,
ai só ver códigos estão comentados, e adaptar conforme sua necessidade.
AJUSTAR SEQUÊNCIA DE ITENS/LINHAS NO PEDIDO (ITEM / SEQUENCIA)
Prevendo se o usuário excluir um item, a rotina corrige, automaticamente.
// ** CODIFICANDO em PHP
// ** Adaptar o nome dos campos a suas tabelas...
// Nas Linhas do detalhe selecione adicione o Campo: PedidoID marque o campo PedidoID como Campo *escondido*.
// Nas Linhas do detalhe selecione adicione o Campo: Item como *Label*.
// Crie um Evento Ajax OnFocus no Próximo campo depois do {Item} e coloque:
GerarSequencia();
// No Evento OnAfterInsert / OnAfterUpdate / OnAfterDelete:
GerarSequencia();
// Metodo PHP > NOVO > GerarSequencia
/* Macro sc_select */
$_Item=1;
$sql ="
SELECT
PedidoID,
Item
FROM
pedidos_itens
WHERE
PedidoID = [glo_PedidoID]
ORDER BY
PedidoID,
Item
";
sc_select(meus_dados, $sql);
/* Erro no select */
if ({meus_dados} === false) {
// Sua Base + _erro
sc_error_message("Ocorreu um erro no acesso ao<BR>banco de dados: {meus_dados_erro}.<BR>");
}
else {
/* Inclua aqui sua rotina de processamento */
// Qtde de Registros Retornados.
$QtdeRegistros=$meus_dados->RecordCount();
if ($meus_dados->EOF) {
// sc_error_message("Nenhum valor foi retornado pelo banco.<BR>");
} else {
while (!$meus_dados->EOF) {
$_PedidoID = $meus_dados->fields[0]; // ou $meus_dados->fields['CodigoClienteID']
$_Item = $meus_dados->fields[1]; // ou $meus_dados->fields['NomeCliente']
$sql="
UPDATE
pedidos_itens
SET
Item = $_Item
WHERE
PedidoID = [glo_PedidoID]
";
sc_exec_sql($sql);
sc_commit_trans();
$_Item++;
// Avança para o próximo registro do BANCO DE DADOS.
$meus_dados->MoveNext();
} // while (!$meus_dados->EOF)
} // if ($meus_dados->EOF)
// Limpa tudo até a conexão
$meus_dados->Close();
} // sc_select(meus_dados, ** Nao deixar aspas aqui...
if (empty({Item})) {
{Item}=$_Item;
}
-------/----------/----------
// CODIFICANDO USANDO STORED PROCEDURE
// Criar em Programação > Metódos PHP > Novo Metódio: GerarSequencia():
/* Macro sc_lookup */
sc_lookup(ultimo_nro, "
SELECT
MAX(Item)+1
FROM
pedidos_itens
WHERE
PedidoID=[glo_PedidoID]
ORDER BY
PedidoID
");
{Item}={ultimo_nro[0][0]}; // Já retornou com o último número + 1.
if (empty({Item})) {
{Item}=1;
}
// Colocar no Evento Evento OnLoadRecord e no OnValidate:
GerarSequencia();
Criar a Procedure no MySQL/MariaDB use o Heidi SQL:
DELIMITER |
CREATE PROCEDURE ajustar_pedido_item(IN parametro1 int(11))
BEGIN
SET @Item=0;
UPDATE
pedidos_itens
SET
Item=@Item:=@Item+1
WHERE
PedidoID = parametro1
ORDER BY
PedidoID, Item;
END|
DELIMITER ;
// Colocar a Procedure em OnAfterInsert, OnAfterUpdate, OnAfterDelete:
// Ajustar/Corrigir Sequência de Itens
$sql="
call ajustar_pedido_item([glo_PedidoID])
";
sc_exec_sql($sql);
Grande Jailton, mais uma vez obrigado por compartilhar conhecimento
vou estudar sim valeu !!
achei interessante deixar o que pesquisei, ele também gera um sequencial
SELECT
ROW_NUMBER() OVER(ORDER BY name ASC) AS Row#,
name, recovery_model_desc
FROM sys.databases
WHERE database_id < 5;
no entanto pelo que pesquisei não tem como colocar o Row# no where