Em geral, o tratamento de erros de banco de dados é parecido com o de outros erros de tempo de execução. Você deve criar um código preparado para eventuais erros e para responder a eles em vez de deixar que o tempo de execução faça isso. De um modo geral, os erros de banco de dados possíveis dividem-se em três categorias: erros de conexão, de sintaxe SQL e de restrição.
Erro de conexão
A maioria dos erros de banco de dados são de conexão, e eles podem ocorrer durante qualquer operação. Embora haja estratégias para prevenir erros de conexão, raramente existe uma forma simples de se recuperar tranquilamente de um erro desse tipo se o banco de dados é um componente crítico do seu aplicativo.
A maior parte dos erros de conexão tem a ver com a maneira como o tempo de execução interage com o sistema operacional, o sistema de arquivos e o arquivo de banco de dados. Por exemplo, ocorre um erro de conexão quando o usuário não tem permissão para criar um arquivo de banco de dados em um determinado local do sistema de arquivos. As seguintes estratégias ajudam a prevenir erros de conexão:
-
Utilize arquivos de banco de dados específicos do usuário
-
Em vez de usar um único arquivo de banco de dados para todos os usuários que utilizam um mesmo computador, dê a cada usuário seu próprio arquivo de banco de dados. O arquivo deve estar localizado em um diretório associado com a conta do usuário. Por exemplo, ele pode estar no diretório de armazenamento do aplicativo, na pasta de documentos do usuário, na área de trabalho dele, e assim por diante.
-
Leve em consideração diferentes tipos de usuário
-
Teste seu aplicativo com diferentes tipos de contas de usuário em diferentes sistemas operacionais. Não suponha que o usuário tem permissão de administrador no computador. Também não presuma que quem instalou o aplicativo é o usuário que o está executando.
-
Leve em consideração localizações de arquivo diferentes
-
Se você permitir que um usuário especifique onde salvar um arquivo de banco de dados ou selecione um arquivo a ser aberto, considere as possíveis localizações de arquivo que os usuários podem usar. Além disso, considere a possibilidade de definir limites quanto aos locais em que os usuários podem armazenar (ou abrir) arquivos de banco de dados. Por exemplo, você só deve permitir que eles abram arquivos existentes no local de armazenamento de suas contas de usuário.
Se acontecer um erro de conexão, é mais provável que ele ocorra na primeira tentativa de criar ou abrir o banco de dados. Isso significa que o usuário não consegue fazer nenhuma operação relacionada a banco de dados no aplicativo. Para certos tipos de erros, como erros de permissão ou somente leitura, uma técnica de recuperação possível consiste em copiar o arquivo de banco de dados para outro local. O aplicativo pode copiar o arquivo de banco de dados para outro local, em que o usuário tenha permissão para criar e gravar em arquivos, e pode usar esse local.
Erros de sintaxe
Um erro de sintaxe ocorre quando uma instrução SQL está formada incorretamente e o aplicativo tenta executá-la. Como as instruções SQL de banco de dados local são criadas como strings, não é possível fazer a verificação da sintaxe SQL durante a compilação. Todas as instruções SQL devem ser executadas para verificar sua sintaxe. Adote as seguintes estratégias para evitar erros de sintaxe SQL:
-
Teste todas as instruções SQL integralmente
-
Se possível, enquanto desenvolve o aplicativo, teste as instruções SQL separadamente antes de codificá-las como texto de instrução no código do aplicativo. Além disso, use uma abordagem de teste do código, como teste de unidade, para criar um conjunto de testes que aplique todas as opções e variações possíveis no código.
-
Use parâmetros de instrução e evite concatenar (gerar dinamicamente) o SQL
-
Usar parâmetros, e evitar instruções SQL criadas dinamicamente, significa que o mesmo texto de instrução SQL é usado sempre que uma instrução é executada. Consequentemente, é bem mais fácil testar suas instruções e limitar a variação possível. Se você tiver de gerar uma instrução SQL dinamicamente, use o mínimo possível de partes dinâmicas na instrução. Além disso, seja cauteloso ao validar qualquer entrada de usuário para se certificar de que ela não causará erros de sintaxe.
Para se recuperar de um erro de sintaxe, um aplicativo precisa de uma lógica complexa que permita examinar uma instrução SQL e corrigir sua sintaxe. Se forem seguidas as diretrizes acima para evitar erros de sintaxe, o código conseguirá identificar qualquer possível origem de tempo de execução de erros de sintaxe SQL (como entradas de usuário utilizadas em uma instrução). Para se recuperar de um erro de sintaxe, oriente o usuário. Indique o que deve ser corrigido para que a instrução seja executada corretamente.
Erros de restrição
Erros de restrição ocorrem quando uma instrução
INSERT
ou
UPDATE
tenta adicionar dados a uma coluna. O erro acontece se os novos dados violam uma das restrições definidas para a tabela ou coluna. O conjunto de restrições possíveis inclui:
-
Restrição exclusiva
-
Indica que, entre todas as linhas de uma tabela, não pode existir valores duplicados em uma coluna. Como alternativa, quando várias colunas são combinadas em uma restrição exclusiva, a combinação de valores dessas colunas não deve ser duplicada. Em outras palavras, em termos da(s) coluna(s) exclusiva(s) especificada(s), cada linha deve ser distinta.
-
Restrição de chave primária
-
Em termos dos dados permitidos e não permitidos por uma restrição, a restrição de chave primária é idêntica a uma restrição exclusiva.
-
Restrição não nula
-
Especifica que uma única coluna não pode armazenar um valor
NULL
e, consequentemente, que em cada linha essa coluna deve ter um valor.
-
Restrição de verificação
-
Permite especificar uma restrição arbitrária em uma ou mais tabelas. Uma restrição de verificação comum é uma regra que define que o valor de uma coluna deve estar dentro de certos limites (por exemplo, que o valor de uma coluna numérica deve ser maior que 0). Outro tipo de restrição de verificação comum especifica relacionamentos entre valores de coluna (por exemplo, que o valor de uma coluna deve ser diferente do de outra coluna na mesma linha).
-
Restrição de tipo de dados (afinidade de coluna)
-
O tempo de execução impõe o tipo de dados de valores de colunas, e ocorre um erro se é feita uma tentativa de armazenar um valor de tipo incorreto em uma coluna. No entanto, em muitas condições os valores são convertidos para corresponder ao tipo de dados declarado da coluna. Consulte
Trabalhar com tipos de dados de banco de dados
para obter mais informações.
O tempo de execução não impõe restrições quanto a valores de chave externa. Em outras palavras, os valores de chave externa não precisam corresponder ao valor de uma chave primária existente.
Além dos tipos de restrição predefinidos, o mecanismo SQL de tempo de execução permite o uso de disparadores. O disparador é como um manipulador de eventos. Ele consiste em um conjunto de instruções predefinidas que são executadas quando acontece uma determinada ação. Por exemplo, é possível definir um disparador que seja executado quando dados forem inseridos ou excluídos de uma tabela específica. Um uso possível de um disparador é examinar alterações feitas em dados e fazer com que ocorra um erro se as condições especificadas não forem atendidas. Consequentemente, um disparador pode atender ao mesmo objetivo de uma restrição, e as estratégias para evitar e se recuperar de erros de restrição também se aplicam a erros gerados por disparadores. Porém, a id de erro dos erros gerados por disparadores é diferente da id de erro dos erros de restrição.
O conjunto de restrições que se aplicam a uma tabela em particular é determinado enquanto você está criando um aplicativo. Elaborar restrições com consciência facilita que você crie o aplicativo para evitar e se recuperar de erros de constrição. No entanto, os erros de restrição são difíceis de prever e impedir sistematicamente. A previsão é difícil porque os erros de restrição só aparecem depois que são adicionados os dados do aplicativo. Os erros de restrição acontecem com dados que são adicionados a um banco de dados após sua criação. Com frequência, esses erros são resultado do relacionamento entre os novos dados e os dados já existentes no banco de dados. As seguintes estratégias podem ajudá-lo a evitar muitos erros de restrição:
-
Planeje cautelosamente a estrutura e as restrições do banco de dados
-
A finalidade das restrições é impor regras de aplicativo e ajudar a proteger a integridade dos dados do banco de dados. Quando estiver planejando seu aplicativo, pense em como estruturar o banco de dados para dar suporte ao aplicativo. Como parte desse processo, identifique regras para seus dados; por exemplo, se certos valores não necessários, se um valor tem um padrão, se são permitidos valores duplicados e assim por diante. Essas regras orientam a definição de restrições do banco de dados.
-
Especifique nomes de coluna explicitamente
-
É possível criar uma instrução
INSERT
sem especificar explicitamente as colunas em que os valores deverão ser inseridos, mas fazê-lo é um risco desnecessário. Quando você nomeia explicitamente as colunas em que os valores deverão ser inseridos, pode permitir valores gerados de forma automática, colunas com valores padrão e colunas que permitam valores
NULL
. Além disso, quando você faz isso pode assegurar que todas as colunas
NOT NULL
terão um valor explícito inserido.
-
Use valores padrão
-
Sempre que você especificar uma restrição
NOT NULL
para uma coluna, se possível, especifique um valor padrão na definição de coluna. O código do aplicativo também pode fornecer valores padrão. Por exemplo, o código pode verificar se uma variável String é
null
e atribuir um valor a ela antes de usá-la para definir um valor de parâmetro de instrução.
-
Valide os dados inseridos pelos usuários
-
Verifique com antecedência os dados inseridos pelos usuários para ter certeza de que obedecem aos limites especificados pelas restrições, principalmente no caso de restrições
NOT NULL
e
CHECK
. Naturalmente, uma restrição
UNIQUE
é mais difícil de verificar porque, para fazer a verificação, é necessário executar uma consulta
SELECT
para determinar se os dados são exclusivos.
-
Use disparadores
-
Você pode criar um disparador que valide (e possivelmente substitua) os dados inseridos ou que tome outras medidas para corrigir dados inválidos. Esse procedimento de validação e correção pode evitar que aconteça um erro de restrição.
Em vários aspectos, é mais difícil evitar os erros de restrição do que outros tipos de erro. Felizmente, existem diversas estratégias para se recuperar de erros de restrição sem tornar o aplicativo instável ou inutilizável:
-
Use algoritmos de conflito
-
Quando você define uma restrição em uma coluna, e quando cria uma instrução
INSERT
ou
UPDATE
, tem a opção de especificar um algoritmo de conflito. Um algoritmo de conflito define a ação que o banco de dados executa quando ocorre uma violação de restrição. Há várias ações possíveis que o mecanismo de banco de dados pode executar. O mecanismo de banco de dados pode encerrar uma única instrução ou uma transação inteira. Ele pode ignorar o erro. Ele pode até mesmo remover dados antigos e substituí-los pelos dados que o código está tentando armazenar.
Para obter mais informações consulte a seção “ON CONFLICT (algoritmos de conflito)” em
Suporte SQL em bancos de dados locais
.
-
Disponibilize feedback de correção
-
É possível identificar antecipadamente o conjunto de restrições que pode afetar um determinado comando SQL. Como consequência, você consegue prever os erros de restrição que podem ser causados por uma instrução. Dispondo dessa informação, você pode desenvolver a lógica do aplicativo para responder a um erro de restrição. Por exemplo, suponha que um aplicativo inclui um formulário de entrada de dados que permite inserir novos produtos. Se a coluna de nome de produto no banco de dados estiver definida com uma restrição
UNIQUE
, a ação de inserir uma linha de novo produto no banco de dados poderá causar um erro de restrição. Consequentemente, o aplicativo deve prever um erro de restrição. Quando o erro acontece, o aplicativo alerta o usuário indicando que o nome de produto especificado já está sendo utilizado e pede a ele para escolher outro nome. Outra resposta possível é permitir que o usuário visualize informações sobre o outro produto que tem o mesmo nome.
|
|
|