#.net #regex
#.net #регулярное выражение
Вопрос:
У нас есть некоторая служба ведения журнала из API, у которой возникли некоторые проблемы с получением базы данных, к которой обращается запрос.
Скажем, запрос выглядит следующим образом:
Select Top 10 * From DataBase..Table
Чего я хотел бы добиться, так это получить «базу данных» или текст перед «..» в строке.
Кроме того, иногда запрос выглядит следующим образом:
Select Top 10 * From DataBase.Schema.Table
Возможно ли получить строку «База данных» в обоих случаях?
Вот что я пытался сделать, но я не настолько хорош в регулярных выражениях.
([A-Z] . ?([A-Z])*(.) [A-Z])
Но это соответствует следующему (в квадратных скобках):
Select Top 10 * From [DataBase..T]able
Спасибо за помощь!
Редактировать: это делается на C #, перед отправкой запроса / запроса в базу данных мы пытаемся регистрировать каждый запрос, который обрабатывает этот метод API.
Комментарии:
1. SQL — сложный язык, и попытка проанализировать его с помощью прямого строкового подхода, такого как регулярное выражение, может быть рискованной, самый надежный способ — использовать анализатор SQL. Для вашего конкретного вопроса с вашим конкретным примером я предлагаю использовать ключевое слово «From», чтобы запустить ваш шаблон и захватить (в группе захвата) все, что не является точкой после любого количества пробелов.
2. Это делается на c #. Это API, который перехватывает запросы и регистрируется в файле перед запросом к базе данных. Это не сделано в SQL Server, извините, если я не понял.
3. имя базы данных может содержать любой символ, включая точку. Более общий и наивный подход заключается в поиске подстрок между «from » и «.», но обратите внимание, что база данных может быть названа даже
[ FROM . ]
Ответ №1:
Как уже упоминалось в комментарии, разбор SQL таким образом — плохая идея из-за сложностей, с которыми вы можете столкнуться. Но если это то, что вы хотите сделать, следующее должно сработать. Это будет работать для операторов select или delete, вставка / обновление не будут работать, поскольку они имеют разную структуру.
public string GetDbName(string sql)
{
var sqlLower = sql.ToLower();
var parts = sqlLower.Split(new string[] { "from " }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length < 2)
{
//something is wrong in sql;
//may be its not a select statement
return null;
}
var tableName = parts[1]
.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
.FirstOrDefault();
var posOfTableName = tableName.LastIndexOf('.');
var dbName = tableName.Substring(0, posOfTableName);
//We can return here, but it will return lower case db name parts
//We can also get the original value as well by looking into original parameter
var indexOfStart = sqlLower.IndexOf(dbName);
return sql.Substring(indexOfStart, dbName.Length);
}
Комментарии:
1. Я использую что-то очень похожее на этот ATM, но мне интересно, есть ли РЕГУЛЯРНОЕ ВЫРАЖЕНИЕ для достижения этого без необходимости разбивать строку и еще много чего. Спасибо!