1

У меня есть пара баз данных (один mssql и один оракул), которыми управляют разные команды. Некоторые данные теперь синхронизируются с помощью хранимой процедуры в таблице mssql. Эта хранимая процедура вызова очень большогоMSSQL Преобразование типа данных

MERGE [mssqltable].[Mytable] as s 
USING THEORACLETABLE.BLA as t 
ON t.[R_ID] = s.[R_ID] 
WHEN MATCHED THEN UPDATE SET [Field1] = s.[Field1], ..., [Brokenfield] = s.[BrokenField] 
WHEN NOT MATCHED BY TARGET THEN 
... another big statement 

поля Brokenfield была числовой один до сегодняшнего дня, и может принимать значения N ULL, 0, 1, .., 24

Теперь команда оракул представила разрывное изменение сегодня по какой-то причине, изменился тип столбца в строку и теперь имеет значения NULL, "", "ALFA", "BRAVO" ... в столбце. Конечно, синхронизация разобралась.

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

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

Редактировать/Разъяснение:
Что мне нужно, это способ сделать кусок кода SQL (хранимой процедуры), принимая вход «ALFA» и возвращение 1, «БРАВО» -> 2, и т.д. и которые можно использовать повторно, чтобы избежать написания огромных ifs в более чем одном месте.

+0

Вы будете нуждаться, чтобы изменить тип данных этого столбца в базе данных SQL Server. Это должен быть (n) varchar (SomeSize). Это зависит от размера столбца на стороне Oracle, чтобы он мог хранить все данные. –

+0

Я хотел бы избежать этого, если это возможно. Это потребует значительного рефакторинга программного обеспечения, которое находится поверх mssql. Сегодня мне нужно сделать онлайн-исправление, и такое изменение в 100 000 LOC-программ, используемых огромной компанией, может быть сделано только для фиксированных дат выпуска с не менее 3-х месяцев тестирования. –

+0

Ну, вы не можете вставить строку, подобную ALFA, в числовой столбец. Вы можете обернуть столбец выражением case и вставить NULL, если он не является допустимым числом.Но то, что вы делаете, - это получение данных из источника, который был числом, и больше не является числом и вставляет это значение в числовой столбец. Значения ДОЛЖНЫ быть числовыми или они не будут выполнены. –

ответ

2

Если вы не можете упростить логику правильных значений, как описано в описании @RichardHansell, вы можете создать таблицу переходов для BrokenField с правильными значениями. Затем вы можете использовать общее табличное выражение или подзапрос с left join на этот пешеходный переход для использования в merge.

create table dbo.BrokenField_Crosswalk (
    BrokenField varchar(32) not null primary key 
    , CorrectedValue int 
); 

insert into dbo.BrokenField_Crosswalk (BrokenField,CorrectedValue) values 
    ('ALFA', 1) 
, ('ALPHA', 1) 
, ('BRAVO', 2) 
... 
go 

И ваш код merge будет выглядеть примерно так:

;with cte as (
    select o.R_ID 
    , o.Field1 
    , BrokenField = cast(isnull(c.CorrectedValue,o.BrokenField) as int) 
    .... 
    from oracle_table.bla as o 
    left join dbo.BrokenField_Crosswalk as c 
) 

merge into [mssqltable].[Mytable] t 
    using cte as s 
    on t.[R_ID] = s.[R_ID] 
    when matched 
    then update set 
     [Field1] = s.[Field1] 
     , ... 
     , [Brokenfield] = s.[BrokenField] 
    when not matched by target 
    then 
+0

выглядит неплохо, я попробую! –

+0

FYI - отлично работает –

+0

@PetrOsipov С удовольствием! Спасибо за сообщение тоже! – SqlZim

0

Если они используют имена с буквой в начале, который идет в последовательности:

A = 1 
B = 2 
C = 3 
etc. 

Тогда вы могли бы сделать что-то вроде этого:

MERGE [mssqltable].[Mytable] as s 
USING THEORACLETABLE.BLA as t 
ON t.[R_ID], 1)) - ASCII('A') + 1 = s.[R_ID] 
WHEN MATCHED THEN UPDATE SET [Field1] = s.[Field1], ..., [Brokenfield] = s.[BrokenField] 
WHEN NOT MATCHED BY TARGET THEN 
... another big statement 

Edit: но на самом деле я повторно прочитайте свой вопрос, и вы говорите о [Brokenfield], являющемся столбец проблем, поэтому мое решение не сработает.

Теперь я не понимаю, так как кажется, что оператор MERGE обновляет таблицу оракула числами, поэтому вам нужно, чтобы отображение работало другим способом, то есть 1 -> ALFA, 2 -> BETA , и т.д.?