AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 42469
Accepted
Archangel33
Archangel33
Asked: 2013-05-18 13:50:43 +0800 CST2013-05-18 13:50:43 +0800 CST 2013-05-18 13:50:43 +0800 CST

Restrições baseadas em outras colunas

  • 772

É possível limitar quais valores são permitidos em uma coluna com base em outros valores na linha?

Por exemplo, minha tabela:

ID  Test_mode  Active
--  ---------  ------
1   1          Null
2   0          1
3   1          0

Existe uma maneira de alterar o valor de Test_modepara 0se um 1for inserido emActive

OU

Se Test_modefor 1 não permite inserção/atualização deActive

OU

Lança algum tipo de erro se Test_modefor 1 e uma inserção/atualização Activefor tentada.

Activesó pode ser NULL, 1, 0, E apenas 1 com Test_mode0.

Espero que isso faça sentido, se não, me avise e atualizarei a pergunta.

sql-server sql-server-2008-r2
  • 3 3 respostas
  • 24127 Views

3 respostas

  • Voted
  1. Best Answer
    Kin Shah
    2013-05-18T19:21:02+08:002013-05-18T19:21:02+08:00

    Em primeiro lugar, bem-vindo ao dba.stackexchange.com e obrigado por sua postagem !!

    É possível limitar quais valores são permitidos em uma coluna com base em outros valores na linha.

    Sim, usando CHECK CONSTRAINTS conforme descrito aqui

    Exemplo :

    create table myTable (ID int identity(1,1)
                            , Test_mode int
                            , Active int 
                            )
    go
    
    -- Active can only be NULL, 1, 0, AND only 1 with Test_mode as 0.
    ALTER TABLE myTable WITH CHECK ADD 
       CONSTRAINT ck_active CHECK (active IS NULL OR active IN (1, 0)) 
       go
    
    -- some test data
    insert into myTable (test_mode, Active) values (1, null)
    insert into myTable (test_mode, Active) values (0, null)
    insert into myTable (test_mode, Active) values (1, 0)
    insert into myTable (test_mode, Active) values (0, 1)
    insert into myTable (test_mode, Active) values (1, 1)
    
    select * from myTable
    
    -- Is there a way to either change the value of Test_mode to 0 if a 1 is inserted into Active
    
    update myTable
    set Test_mode = case when Active = 1 then  0
            else Test_mode 
            end
    where Active = 1
    

    Se Test_modefor 1 não permite inserção/atualização de Active --OU-- Lança algum tipo de erro se Test_mode for 1 e uma inserção/atualização de Active é tentada.

    Use TRY/CATCH conforme descrito aqui

    • 8
  2. Jon Seigel
    2013-05-19T07:41:01+08:002013-05-19T07:41:01+08:00

    A primeira linha de defesa para evitar que dados inválidos entrem em suas tabelas são os tipos de dados das colunas.

    Se um processo tentar inserir ou atualizar uma coluna para um valor que esteja fora do intervalo do tipo de dados (ou NULLse a coluna não permitir NULLs), a operação falhará imediatamente sem que você precise fazer nenhum trabalho extra.

    A seleção do tipo de dados é um dos aspectos mais importantes do design da tabela.

    Então, como você não postou um esquema, vou construir um com base nas informações que você forneceu:

    CREATE TABLE [dbo].[Tests]
    (
        ID int IDENTITY(1, 1) PRIMARY KEY,
        Test_mode bit NOT NULL, /* Based on only seeing 0/1. Maybe tinyint? */
        Active bit NULL
    );
    

    Com base neste design, as combinações disponíveis já se limitam ao seguinte:

    Test_mode ativo
            0 NULO
            0 0
            0 1
            1 NULO
            1 0
            1 1

    Qualquer coisa diferente disso fará com que um erro seja gerado. (O que é uma boa coisa.)


    Existe uma maneira de alterar o valor de Test_mode para 0 se um 1 for inserido em Active

    OU

    Se Test_mode for 1 não permite inserção/atualização de Active

    OU

    Lance algum tipo de erro se Test_mode for 1 e uma inserção/atualização de Active for tentada.

    Ativo só pode ser NULL, 1, 0 e apenas 1 com Test_mode como 0.

    Você deu 4 maneiras diferentes de chegar à combinação permitida de valores (bem, mais ou menos). Estas são estratégias muito diferentes , com comportamentos de implementação muito diferentes.

    Prefiro usar o que chamamos de restrições declarativas . Em outras palavras, o esquema da tabela e seus objetos associados limitam os valores permitidos declarando explicitamente o que é permitido (ou às vezes, o que não é permitido). Na verdade, os próprios tipos de dados da coluna são um tipo de restrição declarativa. Quanto mais próximos dos dados da tabela os valores puderem ser restritos, mais fácil e confiável eles poderão ser restritos. (Em contraste, uma restrição não declarativa ou ativa seria implementada escrevendo uma parte do T-SQL, geralmente um gatilho de tabela ou parte de um procedimento armazenado.)

    As 3 primeiras opções só podem ser implementadas por meios não declarativos. O último, no entanto, é declarativo, então vamos nos concentrar nisso:

    Activesó pode ser NULL, 1, 0, E apenas 1 com Test_mode0.

    Isso define o que você realmente deseja, que são as combinações de valores permitidas na tabela. Observe que as combinações válidas dependem apenas dos valores das colunas dentro da mesma linha . Isso é importante porque determina qual(is) mecanismo(s) pode(m) ser usado(s) para implementar a restrição.

    Nesse caso, podemos usar uma CHECKrestrição , que é um teste verdadeiro/falso que determina se uma linha é válida ou inválida com base nos valores 1 da coluna de uma linha . Se o teste falhar, a operação que tentou alterar a linha falhará com um erro.

    ALTER TABLE [dbo].[Tests] WITH CHECK
        ADD CONSTRAINT CC_Tests_TestMode_Active
            CHECK ((Test_mode != 0) OR ((Active IS NOT NULL) AND (Active = 1)));
    

    Você notará que construí o predicado de forma que ele continue a funcionar mesmo se Test_modefor realmente um tipo inteiro (não anulável). A IS NOT NULLparte é necessária porque as CHECKrestrições permitem linhas em que o predicado é avaliado como undefined.

    1 Eles podem ser usados ​​para verificar fora da linha atual, mas essa é uma prática ruim e não vou entrar nisso aqui. Em vez disso, use um gatilho.

    • 3
  3. Mohamed.Abdo
    2017-08-09T07:28:03+08:002017-08-09T07:28:03+08:00
    CREATE UNIQUE INDEX [UNQ_IndexName]
      ON [dbo].[Table]([Column])
      WHERE   ([Status] in( 'A','D' ) );
    
    • 2

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Conceder acesso a todas as tabelas para um usuário

    • 5 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve