Я нашел хак через DECLARE CONTINUE HANDLER
и GET DIAGNOSTICS CONDITION
, поэтому просто подумал, я должен поделиться им здесь.
Вот мой полный финальный скрипт, который сохраняет резервную копию (синхронизацию) для обеих баз данных users
что это означает, что любое обновление на test_db1
(которое мы можем назвать его производным DB) будет происходить на test_db2
(которое мы можем назвать его как stagingDB):
/*
Create two databases:
1. `test_db1`
2. `test_db2`
and execute below create *Table script* on both databases.
after that execute *Triggers Script* on `test_db1` only..
*/
/*
TABLE STRUCTURE FOR `users`
*/
DROP TABLE IF EXISTS `users`;
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) AUTO_INCREMENT NOT NULL,
`name` varchar(30) NOT NULL,
`age` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
/*
TABLE STRUCTURE FOR `errors`
*/
DROP TABLE IF EXISTS `errors`;
CREATE TABLE IF NOT EXISTS `errors` (
`id` int(11) AUTO_INCREMENT NOT NULL,
`code` varchar(30) NOT NULL,
`message` TEXT NOT NULL,
`query_type` varchar(50) NOT NULL,
`record_id` int(11) NOT NULL,
`on_db` varchar(50) NOT NULL,
`on_table` varchar(50) NOT NULL,
`emailed` TINYINT DEFAULT 0,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
/*
TRIGGERS SCRIPTS FOR INSERT, UPDATE AND DELETE OPERATIONS
*/
DELIMITER //
-- TRIGGER FOR INSERT
DROP TRIGGER IF EXISTS `test_db1_users_ai`;
CREATE TRIGGER `test_db1_users_ai` AFTER INSERT ON `users` FOR EACH ROW
BEGIN
-- Declare variables to hold diagnostics area information
DECLARE errorCode CHAR(5) DEFAULT '00000';
DECLARE errorMessage TEXT DEFAULT '';
-- Declare exception handler for failed insert
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
END;
-- Perform the insert
INSERT INTO `test_db2`.`users` (id, name, age) VALUES (NEW.id, NEW.name, NEW.age);
-- Check whether the insert was successful
IF errorCode != '00000' THEN
INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'insert', NEW.id, 'test_db2', 'users');
END IF;
END; //
-- TRIGGER FOR UPDATE
DROP TRIGGER IF EXISTS `test_db1_users_au`;
CREATE TRIGGER `test_db1_users_au` AFTER UPDATE ON `users` FOR EACH ROW
BEGIN
-- Declare variables to hold diagnostics area information
DECLARE errorCode CHAR(5) DEFAULT '00000';
DECLARE errorMessage TEXT DEFAULT '';
-- Declare exception handler for failed insert
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
END;
-- Perform the update
UPDATE `test_db2`.`users`
SET name = NEW.name,
age = NEW.age
WHERE id = NEW.id;
-- Check whether the update was successful
IF errorCode != '00000' THEN
INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'update', NEW.id, 'test_db2', 'users');
END IF;
END; //
-- TRIGGER FOR DELETE
DROP TRIGGER IF EXISTS `test_db1_users_ad`;
CREATE TRIGGER `test_db1_users_ad` AFTER DELETE ON `users` FOR EACH ROW
BEGIN
-- Declare variables to hold diagnostics area information
DECLARE errorCode CHAR(5) DEFAULT '00000';
DECLARE errorMessage TEXT DEFAULT '';
-- Declare exception handler for failed insert
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
errorCode = RETURNED_SQLSTATE, errorMessage = MESSAGE_TEXT;
END;
-- Perform the delete
DELETE FROM `test_db2`.`users`
WHERE id = OLD.id;
-- Check whether the insert was successful
IF errorCode != '00000' THEN
INSERT INTO `errors` (code, message, query_type, record_id, on_db, on_table) VALUES (errorCode, errorMessage, 'delete', OLD.id, 'test_db2', 'users');
END IF;
END; //
-- DELIMITER;
Hope это поможет другим, когда они придут сюда.
Приветствия,
let dictionary = [
"A" : [1, 2],
"Z" : [3, 4],
"D" : [5, 6]
]
let sortedKeys = Array(dictionary.keys).sorted(<) // ["A", "D", "Z"]
EDIT:
Сортированный массив из приведенного выше кода содержит только ключи, а значения должны быть получены из исходного словаря. Однако 'Dictionary'
также является 'CollectionType'
парами (ключ, значение), и мы можем использовать глобальную функцию 'sorted'
, чтобы получить отсортированный массив, содержащий оба ключа и значения, например:
let sortedKeysAndValues = sorted(dictionary) { $0.0 < $1.0 }
println(sortedKeysAndValues) // [(A, [1, 2]), (D, [5, 6]), (Z, [3, 4])]
EDIT2: в настоящее время предпочитает синтаксис Swift, изменяющийся ежемесячно,
let sortedKeys = Array(dictionary.keys).sort(<) // ["A", "D", "Z"]
Глобальный sorted
устарел.
«отсортировано» в iOS 9 & amp; xcode 7.3, swift 2.2 невозможно, измените «отсортированный» на «sort», например:
let dictionary = ["main course": 10.99, "dessert": 2.99, "salad": 5.99]
let sortedKeysAndValues = Array(dictionary).sort({ $0.0 < $1.0 })
print(sortedKeysAndValues)
//sortedKeysAndValues = ["desert": 2.99, "main course": 10.99, "salad": 5.99]
Для Swift 3 следующий вид возвращает отсортированный словарь по клавишам:
let unsortedDictionary = ["4": "four", "2": "two", "1": "one", "3": "three"]
let sortedDictionary = unsortedDictionary.sorted(by: { $0.0.key < $0.1.key })
print(sortedDictionary)
// ["1": "one", "2": "two", "3": "three", "4": "four"]
Для Swift 4 для меня работало следующее:
let dicNumArray = ["q":[1,2,3,4,5],"a":[2,3,4,5,5],"s":[123,123,132,43,4],"t":[00,88,66,542,321]]
let sortedDic = dicNumArray.sorted { (aDic, bDic) -> Bool in
return aDic.key < bDic.key
}
Обновленная версия ответа Ivica M:
let wordDict = [
"A" : [1, 2],
"Z" : [3, 4],
"D" : [5, 6]
]
let sortedDict = wordDict.sort { $0.0 < $1.0 }
print("\(sortedDict)") //
wordDict.sorted(by: { $0.0 < $1.0 })
Примечание:
Некоторые из вас, похоже, удивлены тем, что результирующий массив не является словарем. Словари нельзя сортировать! Полученный тип данных представляет собой отсортированный массив, как и в ответе @ Ivica.
Binary operator > can not be compared to two
Любые операнды. Downcasting не работает ни
– Sean
2 August 2017 в 03:23
В быстром 4 вы можете написать умнее:
let d = [ 1 : "hello", 2 : "bye", -1 : "foo" ]
d = [Int : String](uniqueKeysWithValues: d.sorted{ $0.key < $1.key })
Я пробовал все вышеперечисленное, в двух словах все, что вам нужно, это
let sorted = dictionary.sorted { $0.key < $1.key }
let keysArraySorted = Array(sorted.map({ $0.key }))
let valuesArraySorted = Array(sorted.map({ $0.value }))
Для Swift 3 для меня работало следующее, и синтаксис Swift 2 не работал:
// menu is a dictionary in this example
var menu = ["main course": 10.99, "dessert": 2.99, "salad": 5.99]
let sortedDict = menu.sorted(by: <)
// without "by:" it does not work in Swift 3
sortedDict
? Что menu
? Этот код также не является допустимым.
– cale_b
12 August 2016 в 16:22
Если вы хотите итерации по клавишам и значениям в сортированном порядке ключей, эта форма довольно кратка
let d = [
"A" : [1, 2],
"Z" : [3, 4],
"D" : [5, 6]
]
for (k,v) in Array(d).sorted({$0.0 < $1.0}) {
println("\(k):\(v)")
}
sort
и sorted
. Swift 2: sort
стал sortInPlace
, а sorted
стал sort
.
– Moritz
16 March 2016 в 19:08
Swift 3 сортируется (по: & lt;)
let dictionary = [
"A" : [1, 2],
"Z" : [3, 4],
"D" : [5, 6]
]
let sortedKeys = Array(dictionary.keys).sorted(by:<) // ["A", "D", "Z"]
let sortedKeys = dictionary.keys.sorted()
– Code Different 27 March 2018 в 12:47