простой способ создания «стандартной» формы выражения SQL Server? - PullRequest
4 голосов
/ 30 июля 2009

Это относится к вычисляемым столбцам и ограничениям по умолчанию (и, возможно, другим выражениям) в SQL Server 2005 (или выше). Оба из них используют произвольное выражение для генерации значения, например, (year+1) для вычисляемого столбца, представляющего «следующий год» (это, очевидно, простой и глупый пример).

Что я пытаюсь сделать: Я хочу иметь возможность определить, соответствует ли существующий вычисляемый столбец (или ограничение по умолчанию) в некоторой таблице предполагаемому определению, где последнее определяется в программном обеспечении схема, которая использовалась для создания таблицы. Я могу получить определение вычисляемого столбца, используя sp_helptext, и определение ограничения по умолчанию из представления каталога sys.default_constraints.

С чем у меня проблемы: Выражения, которые я получаю из вышеупомянутых источников, находятся в нормализованной / стандартной форме, которая не соответствует форме, используемой для создания столбца / ограничения. В приведенном выше примере SQL нормализует выражение до ([year]+(1)). Поэтому простое сравнение строк между этой формой и исходной формой не может надежно определить, являются ли они одинаковыми.

Решения, о которых я уже думал:

  • Создание исходных выражений, чтобы они соответствовали форме SQL. Это требует знания правил, которые SQL использует для создания своей формы, которые не документированы, поэтому это не лучшее решение.
  • Разобрать обе формы в AST и сравнить их. У меня уже есть AST для оригинальной формы, но у меня нет парсера, и я бы не стал его писать.
  • Создайте временную таблицу и добавьте вычисляемый столбец, используя исходное выражение, а затем прочитайте нормализованное выражение. Это было бы довольно надежно, но кажется грязным, поскольку в теории это сравнение должно быть только для чтения.

Может кто-нибудь придумать другой хороший вариант для обработки этого? Я надеюсь, что, возможно, кто-то знает какой-нибудь инструмент отладки / диагностики, который будет отображать входное выражение в нормализованной / стандартной форме.

Ответы [ 3 ]

3 голосов
/ 03 августа 2009

Я также добавлю, что «нормализация» выражения иногда не только добавляет скобки, но и меняет некоторые выражения совсем по-другому!

Например, в MS SQL 2008 Express я создал значение по умолчанию со следующим выражением:

year(getdate()) + 1

но SQL Server меняет его на

(datepart(year,getdate())+(1))

Итак, я не верю, что какие-либо правила или регулярные выражения решат вашу проблему в 100% случаев, поэтому я рекомендую вам объединить несколько методов

1) Прежде всего я думаю, что в вашем случае существует ограниченное количество типичных ограничений, которые обычно существуют в большинстве баз данных. Как правило, есть getdate () и константные числовые выражения (0), (1). Вы можете иметь таблицу этих типичных ограничений, которые помогут вам сопоставить ожидаемые и реальные выражения.

2) Тогда вы можете попробовать очень простое правило, чтобы включить имена всех полей в скобки [] и все константы и математические операции в (), так что вы получите year + 1 , преобразованный в ( [год] + (1)) . Я полагаю, это можно сделать с помощью регулярных выражений.

3) для всех случаев, когда вы не смогли сравнить ожидаемые и фактические результаты, используя 1-й или 2-й метод, вы будете делать то, что предлагали, - создать временную таблицу и сравнить результаты.


РЕДАКТИРОВАТЬ 04.Aug:

Я обнаружил, что при создании значений по умолчанию на уровне базы данных они не будут нормализованы. Странно, а? Но, вероятно, вы можете использовать этот факт и создавать значения по умолчанию на уровне базы данных, которые вы привязываете к столбцам вместо создания ограничений по умолчанию для столбцов (хотя, я полагаю, это будет очень большое изменение в дизайне и потребует огромного обновления существующих баз данных)

Что касается ограничений по умолчанию для столбцов и подхода к динамическому созданию / удалению по умолчанию для получения их нормализованной формы, то здесь приведен простой код C # с использованием библиотеки Microsoft.SqlServer.Management.Smo. Я предлагаю создать одну test_table со столбцами IntTest int, VarcharTest varchar (1), DateTimeTest datetime и т. Д., Т. Е. Только один столбец для каждого типа. В этом случае вы создадите / удалите значения по умолчанию, но вам не нужно будет создавать удаленные таблицы и столбцы, что повысит производительность.

Код C # будет следовать (включая использование Microsoft.SqlServer.Management.Smo;)

        Server server = new Server("localhost\\SQLEXPRESS");
        Database db = server.Databases["test"];
        Table t = db.Tables["test_defaults"];
        //here should be some logic to select column name depending on default data type
        //for example for DateTime defaults we will use "DateTimeTest" column
        Column c = t.Columns["DateTimeTest"];

        //clean up previous results if they exist
        DefaultConstraint constr = c.DefaultConstraint;
        if (constr != null) constr.Drop();

        //create new constraint
        constr = c.AddDefaultConstraint();
        constr.Text = "getdate()";
        constr.Create();
        //after refresh we will have a new text
        constr.Refresh();
        string result = constr.Text;

        //drop it if we don't need it
        constr.Drop();
0 голосов
/ 03 августа 2009

Я бы склонялся к вашему третьему решению (создайте таблицу с этим ограничением и прочитайте ее обратно) - вы можете сделать это с временной таблицей, чтобы она была полуочищенной, и если вы кешируете нормализованную форму, вы нужно только сделать это, когда то, что вы ищете, изменится. Я не уверен, насколько статичны выражения, которые вы ищете, но когда они меняются, просто включите часть процесса сохранения в то, что он создает временную таблицу, применяет ограничение, считывает его из определения и сохраняет вместе с нативной формой ограничения.

Если это не то, что вы ищете (кроме того, что оно не совсем чистое), дайте мне знать, и я могу настроить его по мере необходимости.

0 голосов
/ 03 августа 2009

Я чувствую, что должен быть ответ при подключении к ЦАП (чтобы вы могли запрашивать системные таблицы), но я не могу выяснить, как работает функция 'object_definition'.

Это может быть вопрос для кого-то вроде Kalen Delaney, чтобы выяснить, есть ли публичная функция, с которой эти вещи анализируются.

Rob

...