Как извлечь слово из строки

#.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, но мне интересно, есть ли РЕГУЛЯРНОЕ ВЫРАЖЕНИЕ для достижения этого без необходимости разбивать строку и еще много чего. Спасибо!