Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите с миграцией триггера из Firebird в MS SQL  [new]
RuslanGab
Member

Откуда:
Сообщений: 115
Здравствуйте!
Необходимо написать триггер в, функционал которого будет дублировать существующий .
То что работает в выглядит так:
Здравствуйте!
Необходимо написать триггер в, функционал которого будет дублировать существующий .
То что работает в выглядит так:
as
begin
  if (new.ID is null) then begin
    new.ID = gen_id(TABLENAME_GENID, 1 );
  end
end


В моем понимании примерно так это могло бы выглядеть:
as
begin 
  if ((SELECT ID from inserted) is null) 
  begin (SELECT ID from inserted) = (SELECT IDENT_CURRENT('TABLENAME'))+1;
end;


Однако я получаю ошибку "неверный синтакс" около "=" и "+". Могу предположить что первое потому что вставляемая "таблица" может в теории иметь несколько значений (в моем случае всегда одно, однако () триггер также не хочет съедать), а чем ему плюс не нравится я вообще никак не соображу:(

P.S.: Очень хочется чтобы это получилось в принципе, и если кто подскажет как я уже буду счастлив. А опционально уже синтакс по возможности близкий к имеющемуся (пишеся программа для миграции - чтобы просто посредством Regex поменять что надо и все).
2 май 16, 12:34    [19128171]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
Glory
Member

Откуда:
Сообщений: 104751
RuslanGab
То что работает в выглядит так:
as
begin
  if (new.ID is null) then begin
    new.ID = gen_id(TABLENAME_GENID, 1 );
  end
end

И кто расскажет, какой функционал тут реализован ?

RuslanGab
Однако я получаю ошибку "неверный синтакс" около "=" и "+". Могу предположить что первое потому что вставляемая "таблица" может в теории иметь несколько значений (в моем случае всегда одно, однако () триггер также не хочет съедать), а чем ему плюс не нравится я вообще никак не соображу:(

Изменение данных в таблице всю жизнь производились командами UPDATE и INSERT.
Командой SELECT можно только присвоить значение переменной.
А зачем вы собрались что-то делать с автоматически генерируемым IDENTITY вообще непонятно.
2 май 16, 12:43    [19128178]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
RuslanGab
Member

Откуда:
Сообщений: 115
Функционал - если в вводимой записи нет ID, то присвоить его (считав существующий максимальный) этой самой записи (изменить одно из ее значений), после чего эту запись внести в таблицу.
2 май 16, 12:48    [19128186]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
RuslanGab
Member

Откуда:
Сообщений: 115
еще я не пояснил, отчего может не совсем ясно: "то что работает" это сушествующий триггер в Firebird. К нему претензий нет надо это же сделать в SQL Server.
2 май 16, 12:50    [19128190]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
Glory
Member

Откуда:
Сообщений: 104751
RuslanGab
Функционал - если в вводимой записи нет ID, то присвоить его (считав существующий максимальный) этой самой записи (изменить одно из ее значений), после чего эту запись внести в таблицу.

Сделайте ваше поле IDENTITY и не пишите никакого триггера вовсе.

RuslanGab
еще я не пояснил, отчего может не совсем ясно: "то что работает" это сушествующий триггер в Firebird. К нему претензий нет надо это же сделать в SQL Server.

Задача стоит имено эмулировать Firebird на SQL Server ?
Или все же найти лучшее решение на SQL Server ?
2 май 16, 12:58    [19128215]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
RuslanGab
Member

Откуда:
Сообщений: 115
Glory
Сделайте ваше поле IDENTITY и не пишите никакого триггера вовсе.

Если ключ будет автогенерируемым, не будет возможности "копировать" значения при миграции. Если нет, то опять де будет попытка вставить значение с нулевым ключом и вылет по исключению, а надо как раз в конкретно этих случаях его сгенерировать и сохранить.

Glory
Задача стоит имено эмулировать Firebird на SQL Server ?
Или все же найти лучшее решение на SQL Server ?

Полностью перенести данные на новую базу так чтобы старая программа работала с новой базой как и раньше. В старой программе будет только изменена конфигурация соединения. Соответственно нужно конечно максимально хорошее решение для SQL Server, но принципиально именно полное сохранение функционала.
2 май 16, 13:07    [19128232]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
Glory
Member

Откуда:
Сообщений: 104751
RuslanGab
Если ключ будет автогенерируемым, не будет возможности "копировать" значения при миграции.

Чего ?

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



RuslanGab
Glory
Задача стоит имено эмулировать Firebird на SQL Server ?
Или все же найти лучшее решение на SQL Server ?

Полностью перенести данные на новую базу так чтобы старая программа работала с новой базой как и раньше. В старой программе будет только изменена конфигурация соединения. Соответственно нужно конечно максимально хорошее решение для SQL Server, но принципиально именно полное сохранение функционала.

Если вам нужно перенести только данные, то что вы тогда тут пишите про триггер ?
Лучшее решение для SQL - это IDENTITY без всяких триггеров
2 май 16, 13:15    [19128245]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
iljy
Member

Откуда:
Сообщений: 8711
RuslanGab,

делайте обычный IDENTITY, при начальном переносе данных сделайте один раз SET IDENTITY_INSERT ON. Ну если уж совсем хочется максимально привычно сделать (хотя это глупо, в мсскуле нет per-row триггеров и вообще он ориентирован на операции с множествами, так что переучиваться по любому придется), то сделайте функцию-генератор (примеров реализации - полный гугл) и используйте как DEFAULT CONSTRAINT.
2 май 16, 14:12    [19128329]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53697
RuslanGab
(пишеся программа для миграции - чтобы просто посредством Regex поменять что надо и все).

Не выйдет. В MS SQL то, что ты хочешь, делается instead of триггером. Никак ты регекспом не сгенеришь полный insert into (xxx, ...) select case(case xxx is null then next_value(sequence) else xxx end, .... from inserted
2 май 16, 18:46    [19128950]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
Владислав Колосов
Member

Откуда:
Сообщений: 8805
RuslanGab,

если у вас есть доступ к Firebird с SQL server через установленный драйвер, то можно попробовать воспользоваться мастером импорта данных. В настройках Вы можете указать - копировать ли столбцы идентификаторов IDENTITY.Он сам отключит и включит что требуется.
2 май 16, 19:16    [19128988]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
RuslanGab
Member

Откуда:
Сообщений: 115
Glory
RuslanGab
Если ключ будет автогенерируемым, не будет возможности "копировать" значения при миграции.

Чего ?


Создал для примера таблицу с двумя столбцами - ID (автогенерируемый Id), Name.
Insert into TEST VALUES
('some name')

Ok
Insert into TEST VALUES
(5, 'some name')

Error 8101: An explicit value for the identity column in table '%.*ls' can only be specified when a column list is used and IDENTITY_INSERT is ON.

Т.е. при миграции я не смогу вставлять существующие ID. SET IDENTITY_INSERT ON по совету iljy решает проблему - наверное попробую пойти этим путем

Glory
Если вам нужно перенести только данные, то что вы тогда тут пишите про триггер ?
Лучшее решение для SQL - это IDENTITY без всяких триггеров

Нет увы нужна полная структура с views, триггерами и индексами. Я в принципе почти все сделал только тут затык образовался намертво:( Я не до конца понимаю как работает программа (ее как и базу писали 10 лет назад и это был не я), так что и стараюсь перенести максимально корректно чтобы нигде ничего впоследствии не вылезло...

Dimitry Sibiryakov
Не выйдет. В MS SQL то, что ты хочешь, делается instead of триггером. Никак ты регекспом не сгенеришь полный insert into (xxx, ...)

Почему же: если таблицы созданы верно и идентичны (там конечно с типами данных пришлось попрыгать малость и прочими мелочами) то встроенный BulkCopy из C# вполне себе справляется. Я еще всю базу не пускал но десяток простых таблиц перенес без вопросов.

Владислав Колосов
можно попробовать воспользоваться мастером импорта данных. В настройках Вы можете указать - копировать ли столбцы идентификаторов IDENTITY.Он сам отключит и включит что требуется.

О как. Интересно весьма. Погуглю. Спасибо!

Всем спасибо!
3 май 16, 11:20    [19130133]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
Glory
Member

Откуда:
Сообщений: 104751
RuslanGab
Т.е. при миграции я не смогу вставлять существующие ID.

Если вы не будете читать сообщения сервера и документацию, то вы вообще ничего не сможете

RuslanGab
Нет увы нужна полная структура с views, триггерами и индексами. Я в принципе почти все сделал только тут затык образовался намертво:( Я не до конца понимаю как работает программа (ее как и базу писали 10 лет назад и это был не я), так что и стараюсь перенести максимально корректно чтобы нигде ничего впоследствии не вылезло...

Вы все время говорите сначала про программный код, а потом про данные. Вы понимаете, что миграцияю кода и миграция данных - это разные задачи ?
Триггер - это программный код. А таблица и индекс - это данные.
3 май 16, 11:33    [19130189]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
iljy
Member

Откуда:
Сообщений: 8711
RuslanGab,

вы не сможете перенести код просто какой-то заменой. Это разные диалекты скуля, они в некоторых случаях используют совсем разные концепции (простейший пример - те же per-row триггеры, before-триггеры).
3 май 16, 16:15    [19130808]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
RuslanGab
Member

Откуда:
Сообщений: 115
iljy, никто и не спорит что "в лоб" это невозможно. Однако куча усилий и работы с Regex помогли - вроде полет пока нормальный.
17 май 16, 23:25    [19186402]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
iljy
Member

Откуда:
Сообщений: 8711
RuslanGab,

не поделитесь, каким чудо-регэкспом вы перевели триггер

as
begin
  if (new.ID is null) then begin
    new.ID = gen_id(TABLENAME_GENID, 1 );
  end
end

?
17 май 16, 23:35    [19186424]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
RuslanGab
Member

Откуда:
Сообщений: 115
iljy,

C#

1. Which trigger has "autoincrement simulation"?
        internal static String needIdentityInsteadTrigger(String firebirdCommand)
        {
            //Check we have "autoincrement" (if "NEW" ID value is NULL generate new ID for this table)
            String pattern = @"(?<=AS\sBEGIN\sIF\s\(NEW\.)(.*?)(?=\s+IS\s+NULL\s*\)\s+THEN\s+)(.*?)(?=\s*=\s*GEN_ID\()(.*?)(?=1 *\);\s*END)";
            Match m = new Regex(pattern, RegexOptions.IgnoreCase).Match(removeWhitespacesAndEnters(firebirdCommand).ToUpper());
            if (m.Success)
            {
                return m.Groups[1].ToString();
            }
            else
            {
                return null;
            }
        }


2. By creating table set it as Identity
String commTEXT = "create table "
---
if .... commTEXT += ....
....
One of cases (1 PK):
                    if (listPK != null && listPK.Count == 1 && listPK.Contains(dr["COLUMN_NAME"].ToString()))
                    {
                        commTEXT = commTEXT.Substring(0, commTEXT.Length - 1) + " PRIMARY KEY,";
                        if (columnToAddIdentity != null && columnToAddIdentity.Equals(dr["COLUMN_NAME"].ToString(), StringComparison.InvariantCultureIgnoreCase))
                        {
                            commTEXT = commTEXT.Substring(0, commTEXT.Length - 1) + " IDENTITY(1, 1),";
                        }
                    }
                    else


3. SET IDENTITY_INSERT ON to make copy of dates with "id" possible
if (columnToAddIdentity != null && columnToAddIdentity.Length > 0)
                    {
                        Program.log("---> Got trigger command, which determined as 'if ID in inserted data is NULL set is as next id for this table'. Instead of trigger would be autoincremented ID field generate.");

                        if (listPK != null && /*listPK.Contains(columnToAddIdentity)*/ listPK.FindAll(s => s.IndexOf(columnToAddIdentity, StringComparison.OrdinalIgnoreCase) >= 0).Count>0)
                        {
                            commTEXT = " SET IDENTITY_INSERT dbo." + tableName + " ON";
                            Console.WriteLine("---> Command to set identity insert on in MS SQL: " + commTEXT);
                            comm = new SqlCommand(commTEXT, sqlConnection);
                            comm.ExecuteNonQuery();
                            Program.log("---> Autoincremented and 'set identity insert' for field " + columnToAddIdentity + " has been generated.");
                        }
                        else
                        {
                            Program.log("---> Autoincremented for field " + columnToAddIdentity + " has been generated.");
                        }

                        if (triggerNameToDelete != null && triggerNameToDelete.Length > 0)
                        {
                            listTriggers.Remove(triggerNameToDelete);
                        }
                        else
                        {
                            Console.WriteLine("!!!! Some trigger was replaced by autoincrement field, but it wasn't removed from list of triggers to write into MS SQL!");
                            Program.log("!!! Some trigger was replaced by autoincrement field, but it wasn't removed from list of triggers to write into MS SQL!");
                        }
                    }


Это конечно только куски кода и не рефакторенные, но думаю суть понятна. По совету из этого топика такие поля сделаны автоинкрементными с возможностью внесения значений для копирования из старой БД. На best practice я не претендую никаким местом, но вроде все получилось - во всяком случае все данные мигрированы а как это будет работать посмотрим.
18 май 16, 17:33    [19190102]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
iljy
Member

Откуда:
Сообщений: 8711
RuslanGab,
а, т.е. вы такие триггеры просто удалили? Ну да, вариант.
18 май 16, 19:47    [19190563]     Ответить | Цитировать Сообщить модератору
 Re: Помогите с миграцией триггера из Firebird в MS SQL  [new]
RuslanGab
Member

Откуда:
Сообщений: 115
iljy,

по сути да удалил. Ничего лучше не придумал и лучшего совета не получил:)
19 май 16, 02:01    [19191485]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить