Doctrine2 фиксирует порядок при удалении сущностей [duplicate]

Что такое «неопределенный ссылочный / неразрешенный внешний символ»

Я попытаюсь объяснить, что такое «неопределенный ссылочный / неразрешенный внешний символ».

note : я использую g ++ и Linux, и все примеры для него

Например, у нас есть некоторый код

// src1.cpp
void print();

static int local_var_name; // 'static' makes variable not visible for other modules
int global_var_name = 123;

int main()
{
    print();
    return 0;
}

и

// src2.cpp
extern "C" int printf (const char*, ...);

extern int global_var_name;
//extern int local_var_name;

void print ()
{
    // printf("%d%d\n", global_var_name, local_var_name);
    printf("%d\n", global_var_name);
}

Создание объектных файлов

$ g++ -c src1.cpp -o src1.o
$ g++ -c src2.cpp -o src2.o

После фазы ассемблера у нас есть объектный файл, который содержит любые экспортируемые символы. Посмотрите на символы

$ readelf --symbols src1.o
  Num:    Value          Size Type    Bind   Vis      Ndx Name
     5: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    4 _ZL14local_var_name # [1]
     9: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 global_var_name     # [2]

Я отклонил некоторые строки из вывода, потому что они не имеют значения

Итак, мы видим следующие символы для экспорта.

[1] - this is our static (local) variable (important - Bind has a type "LOCAL")
[2] - this is our global variable

src2.cpp ничего не экспортирует, и мы не видели его символов

Свяжите наши объектные файлы

$ g++ src1.o src2.o -o prog

и запустите его

$ ./prog
123

Linker видит экспортированные символы и связывает их. Теперь мы пытаемся раскомментировать строки в src2.cpp, как здесь

// src2.cpp
extern "C" int printf (const char*, ...);

extern int global_var_name;
extern int local_var_name;

void print ()
{
    printf("%d%d\n", global_var_name, local_var_name);
}

, и перестроить объектный файл

$ g++ -c src2.cpp -o src2.o

OK (нет ошибок), потому что мы только строим объектный файл, связь еще не завершена. Попробуйте установить ссылку

$ g++ src1.o src2.o -o prog
src2.o: In function `print()':
src2.cpp:(.text+0x6): undefined reference to `local_var_name'
collect2: error: ld returned 1 exit status

Это произошло потому, что наше local_var_name статично, то есть оно не отображается для других модулей. Теперь глубже. Получить выход фазы перевода

$ g++ -S src1.cpp -o src1.s

// src1.s
look src1.s

    .file   "src1.cpp"
    .local  _ZL14local_var_name
    .comm   _ZL14local_var_name,4,4
    .globl  global_var_name
    .data
    .align 4
    .type   global_var_name, @object
    .size   global_var_name, 4
global_var_name:
    .long   123
    .text
    .globl  main
    .type   main, @function
main:
; assembler code, not interesting for us
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
    .section    .note.GNU-stack,"",@progbits

Итак, мы видели, что для local_var_name нет метки, поэтому линкер не нашел его. Но мы хакеры :), и мы можем это исправить. Откройте src1.s в текстовом редакторе и измените

.local  _ZL14local_var_name
.comm   _ZL14local_var_name,4,4

на

    .globl  local_var_name
    .data
    .align 4
    .type   local_var_name, @object
    .size   local_var_name, 4
local_var_name:
    .long   456789

i.e. вам должно быть как ниже

    .file   "src1.cpp"
    .globl  local_var_name
    .data
    .align 4
    .type   local_var_name, @object
    .size   local_var_name, 4
local_var_name:
    .long   456789
    .globl  global_var_name
    .align 4
    .type   global_var_name, @object
    .size   global_var_name, 4
global_var_name:
    .long   123
    .text
    .globl  main
    .type   main, @function
main:
; ...

мы изменили видимость local_var_name и установили его значение в 456789. Попробуйте построить из него объектный файл

$ g++ -c src1.s -o src2.o

ok, см.

$ readelf --symbols src1.o
8: 0000000000000000     4 OBJECT  GLOBAL DEFAULT    3 local_var_name

В настоящее время local_var_name имеет привязку GLOBAL (LOCAL)

link

$ g++ src1.o src2.o -o prog

и запускает ее

$ ./prog 
123456789

ok, мы взломаем его:)

Итак, в результате - «неопределенная ссылка / неразрешенная внешняя ошибка символа» происходит, когда компоновщик не может найти глобальные символы в объектных файлах.

109
задан Eric Leschinski 18 January 2014 в 21:13
поделиться

13 ответов

Как и вы, вы должны удалить строку из таблицы рекламодателей, прежде чем сможете удалить строку в таблице заданий, на которую она ссылается. Это:

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) 
      REFERENCES `jobs` (`advertiser_id`);

... фактически противоположно тому, что должно быть. Как бы то ни было, это означает, что перед рекламодателями вам придется записывать запись в таблицу заданий. Поэтому вам нужно использовать:

ALTER TABLE `jobs`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) 
      REFERENCES `advertisers` (`advertiser_id`);

После исправления отношения внешнего ключа будет выполняться ваш оператор удаления.

72
ответ дан Raúl Ferràs 24 August 2018 в 09:18
поделиться

Если вы хотите удалить таблицу, вы должны выполнить следующий запрос за один шаг

SET FOREIGN_KEY_CHECKS = 0; DROP TABLE table_name;

12
ответ дан Abin John 24 August 2018 в 09:18
поделиться

У меня была эта проблема в миграции laravel, поэтому порядок отбрасываемых таблиц в методе down () имеет значение

Schema::dropIfExists('groups');
Schema::dropIfExists('contact');

, возможно, не работает, но если вы измените порядок, он будет работать.

Schema::dropIfExists('contact');
Schema::dropIfExists('groups');
2
ответ дан Amin 24 August 2018 в 09:18
поделиться

В соответствии с вашим текущим (возможно, ошибочным) дизайном вы должны удалить строку из таблицы рекламодателей перед , вы можете удалить строку в таблице заданий, на которую она ссылается.

Кроме того, вы можете настроить свой внешний ключ таким образом, чтобы удаление в родительской таблице приводило к удалению строк в дочерних таблицах автоматически. Это называется каскадным удалением. Это выглядит примерно так:

ALTER TABLE `advertisers`
ADD CONSTRAINT `advertisers_ibfk_1`
FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`)
ON DELETE CASCADE;

Сказав, что, как уже указывали другие, ваш внешний ключ чувствует, что он должен идти наоборот, поскольку таблица рекламодателей действительно содержит первичный ключ, а таблица заданий содержит внешний ключ. Я бы переписал его следующим образом:

ALTER TABLE `jobs`
ADD FOREIGN KEY (`advertiser_id`) REFERENCES `advertisers` (`advertiser_id`);

И каскадное удаление не понадобится.

27
ответ дан Asaph 24 August 2018 в 09:18
поделиться

Как насчет этой альтернативы, которую я использовал: разрешить внешнему ключу NULL , а затем выбрать ON DELETE SET NULL.

Лично я предпочитаю использовать оба параметра " ON UPDATE CASCADE ", а также" ON DELETE SET NULL ", чтобы избежать ненужных осложнений, но при настройке вы можете выбрать другой подход. Кроме того, значения NULL'ing внешнего ключа могут в последствии привести к осложнениям, поскольку вы не знаете, что именно там произошло. Поэтому это изменение должно быть в тесной связи с тем, как работает ваш код приложения.

Надеюсь, это поможет.

1
ответ дан Marius Cucuruz 24 August 2018 в 09:18
поделиться

Простым способом было бы отключить проверку внешнего ключа; внесите изменения, затем повторно включите проверку внешнего ключа.

SET FOREIGN_KEY_CHECKS=0; -- to disable them
SET FOREIGN_KEY_CHECKS=1; -- to re-enable them
177
ответ дан michaelb958 24 August 2018 в 09:18
поделиться

, если вам необходимо как можно скорее поддержать клиента и не иметь доступа к

FOREIGN_KEY_CHECKS

, чтобы целостность данных могла быть отключена:

1) удалить внешний ключ

ALTER TABLE `advertisers` 
DROP FOREIGN KEY `advertisers_ibfk_1`;

2) активировать операцию удаления thruogh sql или api

3) добавить внешний ключ обратно в схему

ALTER TABLE `advertisers`
  ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `jobs` (`advertiser_id`);

, однако, это горячее исправление, поэтому оно на свой страх и риск, потому что основной недостаток такого подхода заключается в том, что он необходим для сохранения целостности данных вручную.

0
ответ дан Oleksii Kyslytsyn 24 August 2018 в 09:18
поделиться

Вы можете создать триггер для удаления ссылочных строк перед удалением задания.

    DELIMITER $$
    CREATE TRIGGER before_jobs_delete 
        BEFORE DELETE ON jobs
        FOR EACH ROW 
    BEGIN
        delete from advertisers where advertiser_id=OLD.advertiser_id;
    END$$
    DELIMITER ;
0
ответ дан Patch92 24 August 2018 в 09:18
поделиться

Когда вы создаете базу данных или создаете таблицы

Вы должны добавить, что строка в верхнем скрипте создает базу данных или таблицу

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;

Теперь вы хотите удалить записи из таблицы? то вы пишете как

SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;
DELETE FROM `jobs` WHERE `job_id` =1 LIMIT 1

Удачи!

2
ответ дан Quy Le 24 August 2018 в 09:18
поделиться

Вам нужно удалить его по заказу. В таблицах есть зависимость

1
ответ дан Ran Adler 24 August 2018 в 09:18
поделиться

Если есть несколько заданий с одним и тем же рекламодателем, то ваш внешний ключ должен быть:

ALTER TABLE `jobs`
ADD CONSTRAINT `advertisers_ibfk_1` 
FOREIGN KEY (`advertiser_id`) 
REFERENCES `advertisers` (`advertiser_id`);

В противном случае (если это наоборот в вашем случае), если вы хотите, чтобы строки в рекламодателе будет автоматически удален, если строка в задании будет удалена, добавьте параметр «ON DELETE CASCADE» к вашему внешнему ключу

ALTER TABLE `advertisers`
ADD CONSTRAINT `advertisers_ibfk_1` 
FOREIGN KEY (`advertiser_id`) 
REFERENCES `jobs` (`advertiser_id`);
ON DELETE CASCASE

Проверьте Ограничения внешнего ключа

3
ответ дан Rashmi Pandit 24 August 2018 в 09:18
поделиться

Я думаю, что ваш внешний ключ назад. Попробуйте:

ALTER TABLE 'jobs'
ADD CONSTRAINT `advertisers_ibfk_1` FOREIGN KEY (`advertiser_id`) REFERENCES `advertisers` (`advertiser_id`)
5
ответ дан Tom H 24 August 2018 в 09:18
поделиться

Возможно, вам стоит попробовать УДАЛИТЬ КАСКАД

0
ответ дан user 24 August 2018 в 09:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: