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 / 19468
Accepted
Tim Brigham
Tim Brigham
Asked: 2012-06-19 11:51:31 +0800 CST2012-06-19 11:51:31 +0800 CST 2012-06-19 11:51:31 +0800 CST

MySQL - atualiza automaticamente todas as referências a uma tabela específica para usar na cascata de exclusão?

  • 772

Eu tenho uma tabela específica para um dos meus pacotes de software em uma caixa MySQL 5.1 que preciso descartar algumas centenas de entradas. Estes são nomes de usuário com nomes em maiúsculas, o aplicativo é específico do caso e espera letras minúsculas. No entanto, esta tabela é referenciada por uma tonelada de outras tabelas, algumas das quais podem ter referências a esses usuários.

Existe uma maneira pronta de ajustar as chaves estrangeiras para todas as tabelas em meu banco de dados que fazem referência a uma determinada coluna 'nome de usuário' na tabela 'logins' para ter o atributo on delete cascade definido? Não vejo uma maneira pronta de fazer isso.

O que eu preciso é alterar todas as outras tabelas com chaves estrangeiras dependendo desta tabela para utilizar uma cascata on delete. Espero fazer isso sem alterar manualmente cem tabelas.

O select que estou utilizando é

delete from user where user_name REGEXP '^.*[A-Z].+$';

O problema é que o aplicativo criou IDs de usuário duplicados no campo user_id. Eu só quero manter o número de ID para nomes de usuários criados corretamente.

A seleção acima visa exatamente o que eu quero me livrar. Não tenho acesso à fonte do aplicativo que criou essas entradas.

mysql foreign-key
  • 2 2 respostas
  • 9783 Views

2 respostas

  • Voted
  1. Best Answer
    RolandoMySQLDBA
    2012-06-19T13:04:34+08:002012-06-19T13:04:34+08:00

    AVISO !!!

    Antes de fazer qualquer coisa, mysqldump todo o banco de dados ou tarball /var/lib/mysql

    Se você está preocupado com a diferenciação de maiúsculas e minúsculas, precisa procurar os nomes de usuário de uma maneira especial

    Eu tentei esta pequena experiência

    use test
    DROP TABLE rolando;
    CREATE TABLE rolando
    (id int not null auto_increment,
    name varchar(20),primary key (id));
    INSERT INTO rolando (name) VALUES
    ('rolando'),('Rolando'),
    ('ROLANDO'),('ROLANDO'),
    ('rolando'),('rolando');
    

    Eu carreguei os dados de amostra

    mysql> use test
    Database changed
    mysql> DROP TABLE rolando;
    Query OK, 0 rows affected (0.03 sec)
    
    mysql> CREATE TABLE rolando
        -> (id int not null auto_increment,
        -> name varchar(20),primary key (id));
    Query OK, 0 rows affected (0.07 sec)
    
    mysql> INSERT INTO rolando (name) VALUES
        -> ('rolando'),('Rolando'),
        -> ('ROLANDO'),('ROLANDO'),
        -> ('rolando'),('rolando');
    Query OK, 6 rows affected (0.08 sec)
    Records: 6  Duplicates: 0  Warnings: 0
    

    Eu executei essas consultas (observe as diferenças sutis)

    mysql> SELECT name,COUNT(1) FROM rolando GROUP BY name;
    +---------+----------+
    | name    | COUNT(1) |
    +---------+----------+
    | rolando |        6 |
    +---------+----------+
    1 row in set (0.00 sec)
    
    mysql> SELECT name,MD5(name),COUNT(1) FROM rolando GROUP BY name,MD5(name);
    +---------+----------------------------------+----------+
    | name    | MD5(name)                        | COUNT(1) |
    +---------+----------------------------------+----------+
    | ROLANDO | b3f7ba680fe83ab0b5174737e8d536a2 |        2 |
    | Rolando | e0732d78dc135b8fcc33ec79bfa89d1f |        1 |
    | rolando | e80d4ab77eb18a4ca350157fd487d7e2 |        3 |
    +---------+----------------------------------+----------+
    3 rows in set (0.00 sec)
    
    mysql> SELECT name,MD5(name)=MD5(LOWER(name)) from rolando;
    +---------+----------------------------+
    | name    | MD5(name)=MD5(LOWER(name)) |
    +---------+----------------------------+
    | rolando |                          1 |
    | Rolando |                          0 |
    | ROLANDO |                          0 |
    | ROLANDO |                          0 |
    | rolando |                          1 |
    | rolando |                          1 |
    +---------+----------------------------+
    6 rows in set (0.00 sec)
    
    mysql> SELECT name,COUNT(1) FROM rolando GROUP BY name;
    +---------+----------+
    | name    | COUNT(1) |
    +---------+----------+
    | rolando |        6 |
    +---------+----------+
    1 row in set (0.00 sec)
    
    mysql> SELECT name,(name LIKE lower(name)) like1,
        -> (name = binary LOWER(name)) like2 FROM rolando;
    +---------+-------+-------+
    | name    | like1 | like2 |
    +---------+-------+-------+
    | rolando |     1 |     1 |
    | Rolando |     1 |     0 |
    | ROLANDO |     1 |     0 |
    | ROLANDO |     1 |     0 |
    | rolando |     1 |     1 |
    | rolando |     1 |     1 |
    +---------+-------+-------+
    6 rows in set (0.00 sec)
    
    mysql>
    

    Dê esta visão do meu experimento, um nome de usuário com todas as letras maiúsculas ou mistas pode ser igual a todas as letras minúsculas, A MENOS QUE VOCÊ USE BINARYo operador com a comparação

    Eu não acho que BINARYpode ser aplicado a ON DELETE CASCADE.

    No entanto, você pode fazer algo assim: Para excluir todos os nomes de usuário apenas em minúsculas, tente executar um dos seguintes procedimentos:

    DELETE FROM logins WHERE username = BINARY LOWER(username);
    

    ou

    DELETE FROM logins WHERE MD5(username) = MD5(LOWER(username));
    

    Se você executar isso agora, poderá eliminar todos os nomes de usuário nas outras tabelas. Execute isso em vez disso

    SET FOREIGN_KEY_CHECKS=0;
    DELETE FROM logins WHERE username = BINARY LOWER(username);
    

    ou

    SET FOREIGN_KEY_CHECKS=0;
    DELETE FROM logins WHERE MD5(username) = MD5(LOWER(username));
    

    Você terá que ir a todas as tabelas que possuem um nome de usuário e executar

    SET FOREIGN_KEY_CHECKS=0;
    DELETE FROM <whatevertable1> WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP '^.*[A-Z].+$';
    DELETE FROM <whatevertable2> WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP '^.*[A-Z].+$';
    DELETE FROM <whatevertable3> WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP '^.*[A-Z].+$';
    .
    .
    .
    DELETE FROM <whatevertableN> WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP '^.*[A-Z].+$';
    

    Como você tem várias outras tabelas, use o INFORMATION_SCHEMA para fazer o script para você:

    DELETE_SQLFILE=/root/SensitiveDelete.sql
    MYSQL_CONN="-uroot -ppassword"
    echo "SET FOREIGN_KEY_CHECKS=0;" > ${DELETE_SQLFILE}
    mysql ${MYSQL_CONN} -ANe"SELECT CONCAT('DELETE FROM ',table_schema,'.',table_name,' WHERE user_name = BINARY LOWER(user_name) AND user_name REGEXP ''\^.*[A-Z].+$''\) FROM information_schema.columns WHERE column_name='user_name'" >> ${DELETE_SQLFILE}
    cat ${DELETE_SQLFILE}
    

    Se o arquivo estiver correto para você, execute-o no cliente mysql assim

    mysql ${MYSQL_CONN} -A < ${DELETE_SQLFILE}
    

    De uma chance !!!

    • 3
  2. randomx
    2012-06-19T13:09:59+08:002012-06-19T13:09:59+08:00

    Se você realmente precisar criar novas linhas, terá que executar UPDATE em cada linha dependente em cada tabela e definir a chave estrangeira na linha dependente para o ID da nova linha na tabela de logins.


    Não sei por que é necessário excluir essas linhas que possuem dados que as referenciam.

    Por que não?

    • Em vez de referenciar dados diretamente na tabela "logins", seu aplicativo pode chamar um procedimento armazenado que transformará o nome de usuário usando a função UPPER() e/ou fornecerá uma rotina de autenticação mais profunda.
    • ...ou a transformação pode acontecer em linha com o SELECT bruto que o aplicativo já está executando.
    • ...ou transforme no lado do aplicativo.

    Acho que há outras opções aqui além de destruir dados.

    Se, por acaso, o único uso desta tabela for logins E o nome de usuário não for o FK na tabela dependente, você poderá executar:

    CREATE TABLE logins_backup SELECT * FROM logins;    
    UPDATE logins SET username = LOWER(username);
    

    Isso deixará o conteúdo em conformidade com o aplicativo, mas deixará o PK ID intacto

    • 0

relate perguntas

  • Existem ferramentas de benchmarking do MySQL? [fechado]

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

  • Quando é o momento certo para usar o MariaDB em vez do MySQL e por quê?

  • Como um grupo pode rastrear alterações no esquema do banco de dados?

Sidebar

Stats

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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