Eu costumo criar meus bancos de dados seguindo as próximas regras:
- Ninguém além de db_owner e sysadmin tem acesso às tabelas do banco de dados.
- As funções de usuário são controladas na camada do aplicativo. Normalmente, uso uma função de banco de dados para conceder acesso aos modos de exibição, procedimentos e funções armazenados, mas em alguns casos, adiciono uma segunda regra para proteger alguns procedimentos armazenados.
- Uso TRIGGERS para validar inicialmente informações críticas.
CREATE TRIGGER <TriggerName>
ON <MyTable>
[BEFORE | AFTER] INSERT
AS
IF EXISTS (SELECT 1
FROM inserted
WHERE Field1 <> <some_initial_value>
OR Field2 <> <other_initial_value>)
BEGIN
UPDATE MyTable
SET Field1 = <some_initial_value>,
Field2 = <other_initial_value>
...
END
- O DML é executado usando procedimentos armazenados:
sp_MyTable_Insert(@Field1, @Field2, @Field3, ...);
sp_MyTable_Delete(@Key1, @Key2, ...);
sp_MyTable_Update(@Key1, @Key2, @Field3, ...);
Você acha que, nesse cenário, vale a pena usar restrições padrão ou estou adicionando um trabalho extra e desnecessário ao servidor de banco de dados?
Atualizar
Entendo que, usando a restrição DEFAULT, estou fornecendo mais informações a alguém que precise administrar o banco de dados. Mas estou mais interessado em desempenho.
Presumo que o banco de dados esteja sempre verificando os valores padrão, mesmo que eu forneça o valor correto, portanto, estou fazendo o mesmo trabalho duas vezes.
Por exemplo, existe uma maneira de evitar restrições DEFAULT em uma execução de acionador?
sql-server
etsql
como o código na sua pergunta é altamente específico para esse DBMSRespostas:
Hum, por que você assumiria isso? ;-). Dado que os padrões existem para fornecer um valor quando a coluna à qual eles estão anexados não está presente na
INSERT
declaração, eu assumiria exatamente o oposto: que eles serão completamente ignorados se a coluna associada estiver presente naINSERT
declaração.Felizmente, nenhum de nós precisa assumir algo devido a esta afirmação na pergunta:
Perguntas sobre desempenho são quase sempre testáveis. Então, precisamos apenas fazer um teste para permitir que o SQL Server (a verdadeira autoridade aqui) responda a essa pergunta.
CONFIGURAÇÃO
Execute o seguinte uma vez:
Execute os testes 1A e 1B individualmente, não juntos, pois isso distorce o tempo. Execute cada uma delas várias vezes para ter uma noção do tempo médio de cada uma.
Teste 1A
Teste 1B
Execute os testes 2A e 2B individualmente, não juntos, pois isso distorce o tempo. Execute cada uma delas várias vezes para ter uma noção do tempo médio de cada uma.
Teste 2A
Teste 2B
Você deve ver que não há diferença real no tempo entre os testes 1A e 1B, ou entre os testes 2A e 2B. Portanto, não, não há penalidade de desempenho para ter um
DEFAULT
definido, mas não usado.Além disso, além de documentar apenas o comportamento pretendido, você deve ter em mente que é principalmente você quem se importa com as instruções DML sendo completamente contidas nos procedimentos armazenados. O pessoal de suporte não se importa. Os desenvolvedores futuros podem não estar cientes do seu desejo de ter todo o DML encapsulado nesses procedimentos armazenados ou se importar, mesmo que eles saibam. E quem mantiver esse banco de dados após a sua saída (outro projeto ou trabalho) pode não se importar, ou pode não ser capaz de impedir o uso de um ORM, não importa o quanto eles protestem. Portanto, os Padrões podem ajudar a dar uma folga às pessoas ao fazer um
INSERT
, especialmente um ad-hocINSERT
feito por um representante de suporte, pois essa é uma coluna que eles não precisam incluir (é por isso que eu sempre uso padrões na auditoria colunas de data).E, ocorreu-me apenas que pode ser mostrado objetivamente se a
DEFAULT
está marcada ou não quando a coluna associada está presente naINSERT
instrução: simplesmente forneça um valor inválido. O teste a seguir faz exatamente isso:Como você pode ver, quando uma coluna (e um valor, não a palavra-chave
DEFAULT
) é fornecida, o Padrão é 100% ignorado. Sabemos disso porque oINSERT
sucesso. Mas se o padrão for usado, ocorrerá um erro quando ele estiver sendo finalmente executado.Embora a necessidade de evitar restrições padrão (pelo menos nesse contexto) seja completamente desnecessária, por uma questão de integridade, pode-se observar que só seria possível "evitar" uma restrição padrão dentro de um
INSTEAD OF
gatilho, mas não dentro de umAFTER
gatilho. De acordo com a documentação para CREATE TRIGGER :Obviamente, o uso de um
INSTEAD OF
acionador exigiria:AFTER
gatilho que habilita a restriçãoNo entanto, eu não recomendaria exatamente isso.
fonte
CURRENT_TIMESTAMP
colunas de data e hora. Portanto, o teste "fácil" de usar uma expressão inválida não funcionará lá (e um valor inválido não pode ser usado no métodoCREATE TABLE
desde que foi validado) e não tenho tempo para construir o teste de desempenho. Mas suspeito que a maioria dos RDBMSs os trataria da mesma maneira.Não vejo nenhum dano significativo em ter restrições padrão. De fato, vejo uma vantagem específica - você definiu o padrão no mesmo nível de lógica que a própria definição de tabela. Se você possui um valor padrão fornecido no procedimento armazenado, alguém precisa ir até lá para descobrir qual é o valor padrão; e isso não é algo óbvio para alguém novo no sistema, necessariamente (se, por exemplo, você herdar um bilhão de dólares amanhã, comprar sua própria ilha tropical e sair e se mudar para lá, deixando outra seiva pobre para entender as coisas por conta própria).
fonte