Другой способ (взломать) (если вы по какой-либо причине не используете 5.5+), который вы можете использовать:
Если у вас есть обязательное поле, то в течение триггера заданное обязательное поле недействительно значение, такое как NULL. Это будет работать как для INSERT, так и для UPDATE. Обратите внимание, что если NULL является допустимым значением для требуемого поля (по какой-то сумасшедшей причине), то этот подход не будет работать.
BEGIN
-- Force one of the following to be assigned otherwise set required field to null which will throw an error
IF (NEW.`nullable_field_1` IS NULL AND NEW.`nullable_field_2` IS NULL) THEN
SET NEW.`required_id_field`=NULL;
END IF;
END
Если вы используете 5.5+, тогда вы можете использовать состояние сигнала как описанных в других ответах:
BEGIN
-- Force one of the following to be assigned otherwise use signal sqlstate to throw a unique error
IF (NEW.`nullable_field_1` IS NULL AND NEW.`nullable_field_2` IS NULL) THEN
SIGNAL SQLSTATE '45000' set message_text='A unique identifier for nullable_field_1 OR nullable_field_2 is required!';
END IF;
END
Более обширный список проблемных символов слова
if (buffer.IndexOf('\u2013') > -1) buffer = buffer.Replace('\u2013', '-');
if (buffer.IndexOf('\u2014') > -1) buffer = buffer.Replace('\u2014', '-');
if (buffer.IndexOf('\u2015') > -1) buffer = buffer.Replace('\u2015', '-');
if (buffer.IndexOf('\u2017') > -1) buffer = buffer.Replace('\u2017', '_');
if (buffer.IndexOf('\u2018') > -1) buffer = buffer.Replace('\u2018', '\'');
if (buffer.IndexOf('\u2019') > -1) buffer = buffer.Replace('\u2019', '\'');
if (buffer.IndexOf('\u201a') > -1) buffer = buffer.Replace('\u201a', ',');
if (buffer.IndexOf('\u201b') > -1) buffer = buffer.Replace('\u201b', '\'');
if (buffer.IndexOf('\u201c') > -1) buffer = buffer.Replace('\u201c', '\"');
if (buffer.IndexOf('\u201d') > -1) buffer = buffer.Replace('\u201d', '\"');
if (buffer.IndexOf('\u201e') > -1) buffer = buffer.Replace('\u201e', '\"');
if (buffer.IndexOf('\u2026') > -1) buffer = buffer.Replace("\u2026", "...");
if (buffer.IndexOf('\u2032') > -1) buffer = buffer.Replace('\u2032', '\'');
if (buffer.IndexOf('\u2033') > -1) buffer = buffer.Replace('\u2033', '\"');
Обратите внимание, что у вас есть поврежденный файл CSV. Беспорядочная замена всех цитат типографа прямыми не обязательно исправит ваш файл. Насколько вы знаете, некоторые цитаты типографа должны были присутствовать как часть значения поля. Замена их прямыми кавычками также может не дать вам действительный файл CSV.
Я не думаю, что есть алгоритмический способ исправить поврежденный файл, как вы описываете. Ваше время может быть лучше потрачено на то, чтобы выяснить, откуда у вас такие недействительные файлы, а затем на этом остановиться. Например, кто-то использует Word для редактирования ваших файлов данных?
Чтобы расширить популярный ответ Ника ван Эша, вот код с именами персонажей в комментариях.
if (buffer.IndexOf('\u2013') > -1) buffer = buffer.Replace('\u2013', '-'); // en dash
if (buffer.IndexOf('\u2014') > -1) buffer = buffer.Replace('\u2014', '-'); // em dash
if (buffer.IndexOf('\u2015') > -1) buffer = buffer.Replace('\u2015', '-'); // horizontal bar
if (buffer.IndexOf('\u2017') > -1) buffer = buffer.Replace('\u2017', '_'); // double low line
if (buffer.IndexOf('\u2018') > -1) buffer = buffer.Replace('\u2018', '\''); // left single quotation mark
if (buffer.IndexOf('\u2019') > -1) buffer = buffer.Replace('\u2019', '\''); // right single quotation mark
if (buffer.IndexOf('\u201a') > -1) buffer = buffer.Replace('\u201a', ','); // single low-9 quotation mark
if (buffer.IndexOf('\u201b') > -1) buffer = buffer.Replace('\u201b', '\''); // single high-reversed-9 quotation mark
if (buffer.IndexOf('\u201c') > -1) buffer = buffer.Replace('\u201c', '\"'); // left double quotation mark
if (buffer.IndexOf('\u201d') > -1) buffer = buffer.Replace('\u201d', '\"'); // right double quotation mark
if (buffer.IndexOf('\u201e') > -1) buffer = buffer.Replace('\u201e', '\"'); // double low-9 quotation mark
if (buffer.IndexOf('\u2026') > -1) buffer = buffer.Replace("\u2026", "..."); // horizontal ellipsis
if (buffer.IndexOf('\u2032') > -1) buffer = buffer.Replace('\u2032', '\''); // prime
if (buffer.IndexOf('\u2033') > -1) buffer = buffer.Replace('\u2033', '\"'); // double prime
Согласно приложению Character Map, которое поставляется с Windows, значения Unicode для фигурных кавычек равны 0x201c и 0x201d. Замените эти значения прямой кавычкой 0x0022, и все будет хорошо.
String.Replace(0x201c, '"');
String.Replace(0x201d, '"');
Когда я столкнулся с этой проблемой, я написал метод расширения для класса String в C #.
public static class StringExtensions
{
public static string StripIncompatableQuotes(this string s)
{
if (!string.IsNullOrEmpty(s))
return s.Replace('\u2018', '\'').Replace('\u2019', '\'').Replace('\u201c', '\"').Replace('\u201d', '\"');
else
return s;
}
}
Это просто заменяет глупые «умные цитаты» обычными цитатами.
[РЕДАКТИРОВАТЬ] Исправлена также поддержка замены «двойных умных кавычек».
У меня есть целая большая ... программа ... которая делает именно это. Вы можете вырвать сценарий и использовать его на свое усмотрение. Он выполняет все виды замен и находится по адресу http://bitbucket.org/nesteruk/typografix
.VB эквивалент того, что написал @Matthew:
Public Module StringExtensions
<Extension()>
Public Function StripIncompatableQuotes(BadString As String) As String
If Not String.IsNullOrEmpty(BadString) Then
Return BadString.Replace(ChrW(&H2018), "'").Replace(ChrW(&H2019), "'").Replace(ChrW(&H201C), """").Replace(ChrW(&H201D), """")
Else
Return BadString
End If
End Function
End Module
это сработало для меня, вы можете попробовать ниже код
string replacedstring = ("your string with smart quotes").Replace('\u201d', '\'');
Спасибо!
Попробуйте это для умных одинарных кавычек, если вышеприведенное не работает:
string.Replace("\342\200\230", "'")
string.Replace("\342\200\231", "'")
Попробуйте также и для умных двойных кавычек:
string.Replace("\342\200\234", '"')
string.Replace("\342\200\235", '"')
У меня также есть программа, которая делает это, источник находится в этом файле из CP-1252 Fixer . Кроме того, он определяет некоторые отображения для преобразования символов в строках RTF, сохраняя при этом все форматирование, что может быть полезно для некоторых.
Это также полное сопоставление всех «умных кавычек» с их низкоуровневыми аналогами, кодами сущностей и ссылками на символы.
Используя ответы Ника и Барбары, вот пример кода со статистикой производительности для 1000000 циклов на моей машине:
input = "shmB6BhLe0gdGU8OxYykZ21vuxLjBo5I1ZTJjxWfyRTTlqQlgz0yUtPu8iNCCcsx78EPsObiPkCpRT8nqRtvM3Bku1f9nStmigaw";
input.Replace('\u2013', '-'); // en dash
input.Replace('\u2014', '-'); // em dash
input.Replace('\u2015', '-'); // horizontal bar
input.Replace('\u2017', '_'); // double low line
input.Replace('\u2018', '\''); // left single quotation mark
input.Replace('\u2019', '\''); // right single quotation mark
input.Replace('\u201a', ','); // single low-9 quotation mark
input.Replace('\u201b', '\''); // single high-reversed-9 quotation mark
input.Replace('\u201c', '\"'); // left double quotation mark
input.Replace('\u201d', '\"'); // right double quotation mark
input.Replace('\u201e', '\"'); // double low-9 quotation mark
input.Replace("\u2026", "..."); // horizontal ellipsis
input.Replace('\u2032', '\''); // prime
input.Replace('\u2033', '\"'); // double prime
Время: 958,1011 миллисекунд
input = "shmB6BhLe0gdGU8OxYykZ21vuxLjBo5I1ZTJjxWfyRTTlqQlgz0yUtPu8iNCCcsx78EPsObiPkCpRT8nqRtvM3Bku1f9nStmigaw";
var inputArray = input.ToCharArray();
for (int i = 0; i < inputArray.Length; i++)
{
switch (inputArray[i])
{
case '\u2013':
inputArray[i] = '-';
break;
// en dash
case '\u2014':
inputArray[i] = '-';
break;
// em dash
case '\u2015':
inputArray[i] = '-';
break;
// horizontal bar
case '\u2017':
inputArray[i] = '_';
break;
// double low line
case '\u2018':
inputArray[i] = '\'';
break;
// left single quotation mark
case '\u2019':
inputArray[i] = '\'';
break;
// right single quotation mark
case '\u201a':
inputArray[i] = ',';
break;
// single low-9 quotation mark
case '\u201b':
inputArray[i] = '\'';
break;
// single high-reversed-9 quotation mark
case '\u201c':
inputArray[i] = '\"';
break;
// left double quotation mark
case '\u201d':
inputArray[i] = '\"';
break;
// right double quotation mark
case '\u201e':
inputArray[i] = '\"';
break;
// double low-9 quotation mark
case '\u2026':
inputArray[i] = '.';
break;
// horizontal ellipsis
case '\u2032':
inputArray[i] = '\'';
break;
// prime
case '\u2033':
inputArray[i] = '\"';
break;
// double prime
}
}
input = new string(inputArray);
Время: 362,0858 миллисекунд
просто вмешавшись, я сделал это с заменой Regex только для обработки некоторых за один раз на основе того, чем я заменяю их:
public static string ReplaceWordChars(this string text)
{
var s = text;
// smart single quotes and apostrophe, single low-9 quotation mark, single high-reversed-9 quotation mark, prime
s = Regex.Replace(s, "[\u2018\u2019\u201A\u201B\u2032]", "'");
// smart double quotes, double prime
s = Regex.Replace(s, "[\u201C\u201D\u201E\u2033]", "\"");
// ellipsis
s = Regex.Replace(s, "\u2026", "...");
// em dashes
s = Regex.Replace(s, "[\u2013\u2014]", "-");
// horizontal bar
s = Regex.Replace(s, "\u2015", "-");
// double low line
s = Regex.Replace(s, "\u2017", "-");
// circumflex
s = Regex.Replace(s, "\u02C6", "^");
// open angle bracket
s = Regex.Replace(s, "\u2039", "<");
// close angle bracket
s = Regex.Replace(s, "\u203A", ">");
// weird tilde and nonblocking space
s = Regex.Replace(s, "[\u02DC\u00A0]", " ");
// half
s = Regex.Replace(s, "[\u00BD]", "1/2");
// quarter
s = Regex.Replace(s, "[\u00BC]", "1/4");
// dot
s = Regex.Replace(s, "[\u2022]", "*");
// degrees
s = Regex.Replace(s, "[\u00B0]", " degrees");
return s;
}
Также еще несколько замен там.