Flask - Last ID row insert

Kristian0

Power Member
Boa noite.

Estou a desenvolver um site em flask e há formulários que inserem dados em varias tabelas:
Morada, DadosPessoais.
O problema é que dependo do IDmorada para poder ligar os dados pessoais com a morada e a forma de solucionar é submeter primeiro a morada, fazer uma querie para ver o IDMax e assim depois usar esse valor para IDMorada (no lado da tabela dos dados pessoais).

Segundo me lembro em php quando fazíamos um INSERT havia forma de saber qual foi o ultimo ID.
Já pesquisei e cheguei ao cursor.lastrowid() mas ele devolve-me sempre 0.

Alguma ideia de como resolver o problema?
 
E se a pessoa B submeter o registo depois da pessoa A mas por azar o servidor teve um arrastamento e o último ID que a query vai selecionar para a pessoa A já é do registo da pessoa B?

Recomendo o seguinte fluxo, com uso de um identificador único, por exemplo, Guid.
1. Gerar Guid1 (código)
2. Inserir registo com Guid1 e ID1 (base de dados)
3. Selecionar ID1 onde Guid1 (base de dados)
4. Inserir restantes registos com ID1 (base de dados)

EDIT: Erro no passo 2, fica:
1. Gerar Guid1 (código)
2. Inserir registo com Guid1 (base de dados)
3. Selecionar ID1 onde Guid1 (base de dados)
4. Inserir restantes registos com ID1 (base de dados)
 
Última edição:
E se a pessoa B submeter o registo depois da pessoa A mas por azar o servidor teve um arrastamento e o último ID que a query vai selecionar para a pessoa A já é do registo da pessoa B?

Recomendo o seguinte fluxo, com uso de um identificador único, por exemplo, Guid.
1. Gerar Guid1 (código)
2. Inserir registo com Guid1 e ID1 (base de dados)
3. Selecionar ID1 onde Guid1 (base de dados)
4. Inserir restantes registos com ID1 (base de dados)

Obrigado pela resposta.
Acabou por ser algo do género o que eu fiz.

Mas como eu não sei o ID_seguinte aquilo que faço é:
1. Gerar Guid1 (código)
2. Inserir registo com Guid1 e ID1 (base de dados)
3. Pesquisar o max(ID) WHERE "as variaveis que vieram do formulário". Não procuro simplesmente o max(ID) porque desta forma protejo contra o facto de alguém ter inserido alguma row entretanto. (base de dados)
4. Inserir restantes registos com ID1 (base de dados).

Ainda assim o workflow é moroso.
E potencia erros, um deles aconteceu precisamente na apresentação do trabalho ao professor.
Tenho um formulario que submete dados em 4 tabelas diferentes.
Portanto na função de submissão tem:
- Faço 1 acesso à base de dados;
- Faz 4 INSERT’s (em tabelas diferentes);
- Faz 5 SELECT’s (para saber quais os ID’s e chaves que tem de preencher na queria final);
(Não por esta ordem)

O que aconteceu foi que o ultimo dos INSERT's falhou (provavelmente algum erro na ligação com o servidor).
E apesar do erro, as informações já submetidas dos outros 3 INSERTS continuaram lá na base de dados...
Já dei voltas para tentar resolver isto e não consigo arranjar uma maneira de transformar isto numa "submissão única" de forma que ou todos são INSERIDOS com sucesso, ou tudo o que foi inserido daquelas submissão é apagado e devolve um erro qualquer.
 
Por lapso no passo 2 incluí o ID1 mas não era suposto porque como tu disseste ele não existe, está a ser criado.
No passo 3 só tens de ir à base dados buscar o ID1 pelo Guid1 (Exemplo: SELECT ID FROM TABELA WHERE GUID = GUID1), a abordagem que usaste não é a mais eficiente daí o "moroso".

Para ultrapassares esse problema tens de recorrer a transações e rollbacks.
Um exemplo prático do StackOverflow.

Mencionei exemplos para SQL mas deve ser transversal a outros tipos de bases de dados.
 
Eu não sei o valor de GUID logo não posso procura-lo dessa forma.
Por exemplo para criar um utilizador, recebo todos os dados e o primeiro INSERT é da morada na tabela morada:

queryMorada = "INSERT INTO morada (Distrito, Concelho, Localidade, Rua, Designacao, CP4, CP3) VALUES ('" + Distrito + "', '" + Concelho + "', '" + Localidade + "', '" + Rua + "', '" + Designacao + "', '" + CP4 + "', '" + CP3 + "');"

Para ir ver o ID deste INSERT das duas uma:
- SELECT max(IDmor) FROM morada (mas se alguém por acaso inseriu outro utilizador fico com o risco de o max(IDmor) não ser o que pretendo.

ou

queryLastIDMor = "SELECT max(IDmor) AS lastIDmor FROM morada \
WHERE Distrito = '" + Distrito + "' AND Concelho = '" + Concelho + "' AND Localidade = '" + Localidade + "' AND Rua = '" + Rua + "' AND Designacao = '" + Designacao + "' AND CP4 = '" + CP4 + "' AND CP3 = '" + CP3 + "';"
(assim tenho sempre a certeza que o meu lastIDmor é o ID da row que eu quero.

Certo?
 
Não... Tens de acrescentar uma coluna GUID na tabela morada.

1. Gerar GUID (Flask é python? acho que é assim mas confirma)
Código:
import uuid
Guid = uuid.uuid1()
2. Inserir registo (nova coluna Guid)
Código:
queryMorada = "INSERT INTO morada (Guid, Distrito, Concelho, Localidade, Rua, Designacao, CP4, CP3)
               VALUES ('" + Guid + "', '" + Distrito + "', '" + Concelho + "', '" + Localidade + "', '" + Rua + "', '" + Designacao + "', '" + CP4 + "', '" + CP3 + "');"
3. Selecionar registo por GUID
Código:
queryLastIDMor = "SELECT ID AS lastIDmor FROM morada
                  WHERE Guid = '" + Guid + "';"
4. Registar noutras tabelas com ID do passo 3.

Nota: Provavelmente inseres primeiro o usuário do que a morada na base de dados, logo este processo deveria ser feito na tabela dos usuários e na tabela morada acrescentas a coluna usuarioID.
 
Última edição:
Voltei a esta questão porque ficou por modificar na altura, devido ao tempo que tinha para entregar o trabalho. Contudo apesar de ja ter entregue e defendido, gostaria de saber fazer as coisas correctamente.

Flask é python exactamente.

Não... Tens de acrescentar uma coluna GUID na tabela morada.
Em que é que o GUID difere do meu idMorada?

Nota: Provavelmente inseres primeiro o usuário do que a morada na base de dados, logo este processo deveria ser feito na tabela dos usuários e na tabela morada acrescentas a coluna usuarioID.
A tabela User tem uma chave estrangeira com a tabela morada.
Dessa forma não posso inserir nenhum utilizador sem lhe dar um IDmorada, e é por isso que a inserção de dados tem essa sequência.

Outro problema que nao consigo resolver é a questão de ir fazendo "Insert's" sequenciais, mas se algum deles falha os dados que ja foram submetidos antes ficam na base de dados sem coerência. Como resolvo isso?
 
Tentaste aplicar o exemplo que dei no post #7?

E antes de tentar ser mais explicito vou deixar-te a minha opinião de que seria mais claro que a chave estrangeira tivesse na tabela morada, isto porque provavelmente a tua aplicação anda à volta do utilizador e não de moradas. Também é mais provável que um utilizador tenha várias moradas (residência e fiscal são dois exemplos) do que uma morada ter vários utilizadores.

Adiante e seguindo a tua estrutura (valores fictícios):
1. Geras o Guid 123456789 no código.
2. Inseres um registo na tabela Morada com os campos todos incluindo o Guid 123456789.
3. Fazes um SELECT do IDmorada na tabela Morada onde o Guid é igual a 123456789.
4. O ponto 3 retorna-te por exemplo o IDmorada 100.
5. Inseres na tabela DadosPessoais os dados do utilizador e com o IDmorada 100.
Voilá!

Para resolver a tua última pergunta também já te respondi, no post #4.
Não deste detalhes sobre que biblioteca estás a usar para comunicar com as bases de dados, nem o tipo de base de dados em si mas dá uma vista de olhos nas páginas que linkei e vais logo perceber o que tens de fazer.
 
Back
Topo