MySQL Before Delete trigger to avoid deleting multiple rows











up vote
1
down vote

favorite












I am trying to avoid deletion of more than 1 row at a time in MySQL by using a BEFORE DELETE trigger.



The sample table and trigger are as below.



Table test:



DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
PRIMARY KEY (`id`));


INSERT INTO `test` (`id`, `a`, `b`)
VALUES (1, 1, 2);

INSERT INTO `test` (`id`, `a`, `b`)
VALUES (2, 3, 4);


Trigger:



DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion;
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON test
FOR EACH STATEMENT
BEGIN

IF(ROW_COUNT()>=2) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;

END //

DELIMITER ;


This is still allowing multiple rows deletion. Even if I change the IF to >= 1, still allows the operation.



I my idea is to avoid operations such as:



DELETE FROM `test` WHERE `id`< 5;


Can you help me? I know that the current version of MySQL doesn't allow FOR EACH STATEMENT triggers.



Thank you!










share|improve this question






















  • I think that ROW_COUNT() will have 0 value (rows affected) only, in a Before Delete Trigger. Since, no rows have been affected until now.
    – Madhur Bhaiya
    Nov 2 at 14:40















up vote
1
down vote

favorite












I am trying to avoid deletion of more than 1 row at a time in MySQL by using a BEFORE DELETE trigger.



The sample table and trigger are as below.



Table test:



DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
PRIMARY KEY (`id`));


INSERT INTO `test` (`id`, `a`, `b`)
VALUES (1, 1, 2);

INSERT INTO `test` (`id`, `a`, `b`)
VALUES (2, 3, 4);


Trigger:



DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion;
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON test
FOR EACH STATEMENT
BEGIN

IF(ROW_COUNT()>=2) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;

END //

DELIMITER ;


This is still allowing multiple rows deletion. Even if I change the IF to >= 1, still allows the operation.



I my idea is to avoid operations such as:



DELETE FROM `test` WHERE `id`< 5;


Can you help me? I know that the current version of MySQL doesn't allow FOR EACH STATEMENT triggers.



Thank you!










share|improve this question






















  • I think that ROW_COUNT() will have 0 value (rows affected) only, in a Before Delete Trigger. Since, no rows have been affected until now.
    – Madhur Bhaiya
    Nov 2 at 14:40













up vote
1
down vote

favorite









up vote
1
down vote

favorite











I am trying to avoid deletion of more than 1 row at a time in MySQL by using a BEFORE DELETE trigger.



The sample table and trigger are as below.



Table test:



DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
PRIMARY KEY (`id`));


INSERT INTO `test` (`id`, `a`, `b`)
VALUES (1, 1, 2);

INSERT INTO `test` (`id`, `a`, `b`)
VALUES (2, 3, 4);


Trigger:



DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion;
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON test
FOR EACH STATEMENT
BEGIN

IF(ROW_COUNT()>=2) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;

END //

DELIMITER ;


This is still allowing multiple rows deletion. Even if I change the IF to >= 1, still allows the operation.



I my idea is to avoid operations such as:



DELETE FROM `test` WHERE `id`< 5;


Can you help me? I know that the current version of MySQL doesn't allow FOR EACH STATEMENT triggers.



Thank you!










share|improve this question













I am trying to avoid deletion of more than 1 row at a time in MySQL by using a BEFORE DELETE trigger.



The sample table and trigger are as below.



Table test:



DROP TABLE IF EXISTS `test`;
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
PRIMARY KEY (`id`));


INSERT INTO `test` (`id`, `a`, `b`)
VALUES (1, 1, 2);

INSERT INTO `test` (`id`, `a`, `b`)
VALUES (2, 3, 4);


Trigger:



DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion;
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON test
FOR EACH STATEMENT
BEGIN

IF(ROW_COUNT()>=2) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;

END //

DELIMITER ;


This is still allowing multiple rows deletion. Even if I change the IF to >= 1, still allows the operation.



I my idea is to avoid operations such as:



DELETE FROM `test` WHERE `id`< 5;


Can you help me? I know that the current version of MySQL doesn't allow FOR EACH STATEMENT triggers.



Thank you!







mysql triggers sql-delete delete-row






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 2 at 14:28









Gustavo Lessa

153




153












  • I think that ROW_COUNT() will have 0 value (rows affected) only, in a Before Delete Trigger. Since, no rows have been affected until now.
    – Madhur Bhaiya
    Nov 2 at 14:40


















  • I think that ROW_COUNT() will have 0 value (rows affected) only, in a Before Delete Trigger. Since, no rows have been affected until now.
    – Madhur Bhaiya
    Nov 2 at 14:40
















I think that ROW_COUNT() will have 0 value (rows affected) only, in a Before Delete Trigger. Since, no rows have been affected until now.
– Madhur Bhaiya
Nov 2 at 14:40




I think that ROW_COUNT() will have 0 value (rows affected) only, in a Before Delete Trigger. Since, no rows have been affected until now.
– Madhur Bhaiya
Nov 2 at 14:40












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










Firstly, getting some syntax error(s) out of our way, from your original attempt:




  • Instead of FOR EACH STATEMENT, it should be FOR EACH ROW.

  • Since you have already defined the Delimiter to //; you need to use // (instead of ;) in the DROP TRIGGER IF EXISTS .. statement.


  • Row_Count() will have 0 value in a Before Delete Trigger, as no rows have been updated yet. So this approach will not work.


Now, the trick here is to use Session-level Accessible (and Persistent) user-defined variables. We can define a variable, let's say @rows_being_deleted, and later check whether it is already defined or not.



For Each Row runs the same set of statements for every row being deleted. So, we will just check whether the session variable already exists or not. If it does not, we can define it. So basically, for the first row (being deleted), it will get defined, which will persist as long as the session is there.



Now if there are more rows to be deleted, Trigger would be running the same set of statements for the remaining rows. In the second row, the previously defined variable would be found now, and we can simply throw an exception now.



Note that there is a chance that within the same session, multiple delete statements may get triggered. So before throwing exception, we need to set the @rows_being_deleted value back to null.



Following will work:



DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion //
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON `test`
FOR EACH ROW
BEGIN

-- check if the variable is already defined or not
IF( @rows_being_deleted IS NULL ) THEN
SET @rows_being_deleted = 1; -- set its value

ELSE -- it already exists and we are in next "row"

-- just for testing to check the row count
-- SET @rows_being_deleted = @rows_being_deleted + 1;

-- We have to reset it to null, as within same session
-- another delete statement may be triggered.
SET @rows_being_deleted = NULL;

-- throw exception
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;

END //

DELIMITER ;




DB Fiddle Demo 1: Trying to delete more than row.



DELETE FROM `test` WHERE `id`< 5;


Result:




Query Error: Error: ER_SIGNAL_EXCEPTION: Cannot delete more than one
order per time!






DB Fiddle Demo 2: Trying to delete only one row



Query #1



DELETE FROM `test` WHERE `id` = 1;



Deletion successfully happened. We can check the remaining rows using Select.




Query #2



SELECT * FROM `test`;

| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |





share|improve this answer



















  • 1




    Thanks! The statement was a typo, but the delimiter part was driving me insane. Until I inserted it before the Delimiter.
    – Gustavo Lessa
    Nov 2 at 23:33






  • 1




    @GustavoLessa before set signal state we can set it to null back again. Please check the edited answer.
    – Madhur Bhaiya
    2 days ago






  • 1




    Thanks Madhur. I replied to your solution here and started editing the answer to add exactly the same line you added now. You were faster than me =)
    – Gustavo Lessa
    2 days ago











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53120440%2fmysql-before-delete-trigger-to-avoid-deleting-multiple-rows%23new-answer', 'question_page');
}
);

Post as a guest
































1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote



accepted










Firstly, getting some syntax error(s) out of our way, from your original attempt:




  • Instead of FOR EACH STATEMENT, it should be FOR EACH ROW.

  • Since you have already defined the Delimiter to //; you need to use // (instead of ;) in the DROP TRIGGER IF EXISTS .. statement.


  • Row_Count() will have 0 value in a Before Delete Trigger, as no rows have been updated yet. So this approach will not work.


Now, the trick here is to use Session-level Accessible (and Persistent) user-defined variables. We can define a variable, let's say @rows_being_deleted, and later check whether it is already defined or not.



For Each Row runs the same set of statements for every row being deleted. So, we will just check whether the session variable already exists or not. If it does not, we can define it. So basically, for the first row (being deleted), it will get defined, which will persist as long as the session is there.



Now if there are more rows to be deleted, Trigger would be running the same set of statements for the remaining rows. In the second row, the previously defined variable would be found now, and we can simply throw an exception now.



Note that there is a chance that within the same session, multiple delete statements may get triggered. So before throwing exception, we need to set the @rows_being_deleted value back to null.



Following will work:



DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion //
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON `test`
FOR EACH ROW
BEGIN

-- check if the variable is already defined or not
IF( @rows_being_deleted IS NULL ) THEN
SET @rows_being_deleted = 1; -- set its value

ELSE -- it already exists and we are in next "row"

-- just for testing to check the row count
-- SET @rows_being_deleted = @rows_being_deleted + 1;

-- We have to reset it to null, as within same session
-- another delete statement may be triggered.
SET @rows_being_deleted = NULL;

-- throw exception
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;

END //

DELIMITER ;




DB Fiddle Demo 1: Trying to delete more than row.



DELETE FROM `test` WHERE `id`< 5;


Result:




Query Error: Error: ER_SIGNAL_EXCEPTION: Cannot delete more than one
order per time!






DB Fiddle Demo 2: Trying to delete only one row



Query #1



DELETE FROM `test` WHERE `id` = 1;



Deletion successfully happened. We can check the remaining rows using Select.




Query #2



SELECT * FROM `test`;

| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |





share|improve this answer



















  • 1




    Thanks! The statement was a typo, but the delimiter part was driving me insane. Until I inserted it before the Delimiter.
    – Gustavo Lessa
    Nov 2 at 23:33






  • 1




    @GustavoLessa before set signal state we can set it to null back again. Please check the edited answer.
    – Madhur Bhaiya
    2 days ago






  • 1




    Thanks Madhur. I replied to your solution here and started editing the answer to add exactly the same line you added now. You were faster than me =)
    – Gustavo Lessa
    2 days ago















up vote
1
down vote



accepted










Firstly, getting some syntax error(s) out of our way, from your original attempt:




  • Instead of FOR EACH STATEMENT, it should be FOR EACH ROW.

  • Since you have already defined the Delimiter to //; you need to use // (instead of ;) in the DROP TRIGGER IF EXISTS .. statement.


  • Row_Count() will have 0 value in a Before Delete Trigger, as no rows have been updated yet. So this approach will not work.


Now, the trick here is to use Session-level Accessible (and Persistent) user-defined variables. We can define a variable, let's say @rows_being_deleted, and later check whether it is already defined or not.



For Each Row runs the same set of statements for every row being deleted. So, we will just check whether the session variable already exists or not. If it does not, we can define it. So basically, for the first row (being deleted), it will get defined, which will persist as long as the session is there.



Now if there are more rows to be deleted, Trigger would be running the same set of statements for the remaining rows. In the second row, the previously defined variable would be found now, and we can simply throw an exception now.



Note that there is a chance that within the same session, multiple delete statements may get triggered. So before throwing exception, we need to set the @rows_being_deleted value back to null.



Following will work:



DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion //
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON `test`
FOR EACH ROW
BEGIN

-- check if the variable is already defined or not
IF( @rows_being_deleted IS NULL ) THEN
SET @rows_being_deleted = 1; -- set its value

ELSE -- it already exists and we are in next "row"

-- just for testing to check the row count
-- SET @rows_being_deleted = @rows_being_deleted + 1;

-- We have to reset it to null, as within same session
-- another delete statement may be triggered.
SET @rows_being_deleted = NULL;

-- throw exception
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;

END //

DELIMITER ;




DB Fiddle Demo 1: Trying to delete more than row.



DELETE FROM `test` WHERE `id`< 5;


Result:




Query Error: Error: ER_SIGNAL_EXCEPTION: Cannot delete more than one
order per time!






DB Fiddle Demo 2: Trying to delete only one row



Query #1



DELETE FROM `test` WHERE `id` = 1;



Deletion successfully happened. We can check the remaining rows using Select.




Query #2



SELECT * FROM `test`;

| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |





share|improve this answer



















  • 1




    Thanks! The statement was a typo, but the delimiter part was driving me insane. Until I inserted it before the Delimiter.
    – Gustavo Lessa
    Nov 2 at 23:33






  • 1




    @GustavoLessa before set signal state we can set it to null back again. Please check the edited answer.
    – Madhur Bhaiya
    2 days ago






  • 1




    Thanks Madhur. I replied to your solution here and started editing the answer to add exactly the same line you added now. You were faster than me =)
    – Gustavo Lessa
    2 days ago













up vote
1
down vote



accepted







up vote
1
down vote



accepted






Firstly, getting some syntax error(s) out of our way, from your original attempt:




  • Instead of FOR EACH STATEMENT, it should be FOR EACH ROW.

  • Since you have already defined the Delimiter to //; you need to use // (instead of ;) in the DROP TRIGGER IF EXISTS .. statement.


  • Row_Count() will have 0 value in a Before Delete Trigger, as no rows have been updated yet. So this approach will not work.


Now, the trick here is to use Session-level Accessible (and Persistent) user-defined variables. We can define a variable, let's say @rows_being_deleted, and later check whether it is already defined or not.



For Each Row runs the same set of statements for every row being deleted. So, we will just check whether the session variable already exists or not. If it does not, we can define it. So basically, for the first row (being deleted), it will get defined, which will persist as long as the session is there.



Now if there are more rows to be deleted, Trigger would be running the same set of statements for the remaining rows. In the second row, the previously defined variable would be found now, and we can simply throw an exception now.



Note that there is a chance that within the same session, multiple delete statements may get triggered. So before throwing exception, we need to set the @rows_being_deleted value back to null.



Following will work:



DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion //
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON `test`
FOR EACH ROW
BEGIN

-- check if the variable is already defined or not
IF( @rows_being_deleted IS NULL ) THEN
SET @rows_being_deleted = 1; -- set its value

ELSE -- it already exists and we are in next "row"

-- just for testing to check the row count
-- SET @rows_being_deleted = @rows_being_deleted + 1;

-- We have to reset it to null, as within same session
-- another delete statement may be triggered.
SET @rows_being_deleted = NULL;

-- throw exception
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;

END //

DELIMITER ;




DB Fiddle Demo 1: Trying to delete more than row.



DELETE FROM `test` WHERE `id`< 5;


Result:




Query Error: Error: ER_SIGNAL_EXCEPTION: Cannot delete more than one
order per time!






DB Fiddle Demo 2: Trying to delete only one row



Query #1



DELETE FROM `test` WHERE `id` = 1;



Deletion successfully happened. We can check the remaining rows using Select.




Query #2



SELECT * FROM `test`;

| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |





share|improve this answer














Firstly, getting some syntax error(s) out of our way, from your original attempt:




  • Instead of FOR EACH STATEMENT, it should be FOR EACH ROW.

  • Since you have already defined the Delimiter to //; you need to use // (instead of ;) in the DROP TRIGGER IF EXISTS .. statement.


  • Row_Count() will have 0 value in a Before Delete Trigger, as no rows have been updated yet. So this approach will not work.


Now, the trick here is to use Session-level Accessible (and Persistent) user-defined variables. We can define a variable, let's say @rows_being_deleted, and later check whether it is already defined or not.



For Each Row runs the same set of statements for every row being deleted. So, we will just check whether the session variable already exists or not. If it does not, we can define it. So basically, for the first row (being deleted), it will get defined, which will persist as long as the session is there.



Now if there are more rows to be deleted, Trigger would be running the same set of statements for the remaining rows. In the second row, the previously defined variable would be found now, and we can simply throw an exception now.



Note that there is a chance that within the same session, multiple delete statements may get triggered. So before throwing exception, we need to set the @rows_being_deleted value back to null.



Following will work:



DELIMITER //
DROP TRIGGER IF EXISTS prevent_multiple_deletion //
CREATE TRIGGER prevent_multiple_deletion
BEFORE DELETE ON `test`
FOR EACH ROW
BEGIN

-- check if the variable is already defined or not
IF( @rows_being_deleted IS NULL ) THEN
SET @rows_being_deleted = 1; -- set its value

ELSE -- it already exists and we are in next "row"

-- just for testing to check the row count
-- SET @rows_being_deleted = @rows_being_deleted + 1;

-- We have to reset it to null, as within same session
-- another delete statement may be triggered.
SET @rows_being_deleted = NULL;

-- throw exception
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Cannot delete more than one order per time!';
END IF;

END //

DELIMITER ;




DB Fiddle Demo 1: Trying to delete more than row.



DELETE FROM `test` WHERE `id`< 5;


Result:




Query Error: Error: ER_SIGNAL_EXCEPTION: Cannot delete more than one
order per time!






DB Fiddle Demo 2: Trying to delete only one row



Query #1



DELETE FROM `test` WHERE `id` = 1;



Deletion successfully happened. We can check the remaining rows using Select.




Query #2



SELECT * FROM `test`;

| id | a | b |
| --- | --- | --- |
| 2 | 3 | 4 |






share|improve this answer














share|improve this answer



share|improve this answer








edited 2 days ago

























answered Nov 2 at 14:56









Madhur Bhaiya

13.8k52035




13.8k52035








  • 1




    Thanks! The statement was a typo, but the delimiter part was driving me insane. Until I inserted it before the Delimiter.
    – Gustavo Lessa
    Nov 2 at 23:33






  • 1




    @GustavoLessa before set signal state we can set it to null back again. Please check the edited answer.
    – Madhur Bhaiya
    2 days ago






  • 1




    Thanks Madhur. I replied to your solution here and started editing the answer to add exactly the same line you added now. You were faster than me =)
    – Gustavo Lessa
    2 days ago














  • 1




    Thanks! The statement was a typo, but the delimiter part was driving me insane. Until I inserted it before the Delimiter.
    – Gustavo Lessa
    Nov 2 at 23:33






  • 1




    @GustavoLessa before set signal state we can set it to null back again. Please check the edited answer.
    – Madhur Bhaiya
    2 days ago






  • 1




    Thanks Madhur. I replied to your solution here and started editing the answer to add exactly the same line you added now. You were faster than me =)
    – Gustavo Lessa
    2 days ago








1




1




Thanks! The statement was a typo, but the delimiter part was driving me insane. Until I inserted it before the Delimiter.
– Gustavo Lessa
Nov 2 at 23:33




Thanks! The statement was a typo, but the delimiter part was driving me insane. Until I inserted it before the Delimiter.
– Gustavo Lessa
Nov 2 at 23:33




1




1




@GustavoLessa before set signal state we can set it to null back again. Please check the edited answer.
– Madhur Bhaiya
2 days ago




@GustavoLessa before set signal state we can set it to null back again. Please check the edited answer.
– Madhur Bhaiya
2 days ago




1




1




Thanks Madhur. I replied to your solution here and started editing the answer to add exactly the same line you added now. You were faster than me =)
– Gustavo Lessa
2 days ago




Thanks Madhur. I replied to your solution here and started editing the answer to add exactly the same line you added now. You were faster than me =)
– Gustavo Lessa
2 days ago


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53120440%2fmysql-before-delete-trigger-to-avoid-deleting-multiple-rows%23new-answer', 'question_page');
}
);

Post as a guest




















































































Popular posts from this blog

Xamarin.iOS Cant Deploy on Iphone

Glorious Revolution

Dulmage-Mendelsohn matrix decomposition in Python