Компонент поиска не может сопоставить пустые строки при использовании полного кеша

У меня есть компонент поиска a с таблицей поиска, которая повторно использует столбец varchar(4) с 3 возможными значениями: «T», «R» или «» (пустая строка).

Я использую соединение OLE DB для таблицы поиска и пробовал прямой доступ к таблице, а также указание запроса с RTRIM() в столбце, чтобы убедиться, что строка пуста, а не "пустая строка некоторую длину».

Если я устанавливаю режим кеша «Частичный кеш», все работает нормально (либо с прямым чтением таблицы, либо с использованием запроса обрезки), а пустые строки входной таблицы правильно сопоставляются с соответствующей строкой таблицы поиска.

Однако, если я изменю режим кеша на «Полный кеш», ни одна из пустых строк не будет совпадать.

Я проверил, что тип данных DT_STR и длина 4 совпадают в таблице поиска и во входной таблице.

Есть ли что-то, что объясняет такое поведение? Можно ли его изменить?

ПРИМЕЧАНИЕ. Это не задокументированная проблема с нулевыми значениями. Речь идет о пустых строках.


person JotaBe    schedule 03.11.2014    source источник
comment
Я не могу воспроизвести эту проблему. Не могли бы вы предоставить определение таблицы для столбца поиска и какую сортировку вы используете? Кроме того, вы также обрезаете значение потока данных, которое вы просматриваете, и это тоже varchar (4)? Если в нем есть пробелы или невидимые символы, поиск завершится ошибкой.   -  person Mark Wojciechowicz    schedule 03.11.2014


Ответы (2)


Где-то у вас есть конечные пробелы, либо в вашем источнике, либо в вашем поиске.

Рассмотрим следующий исходный запрос.

SELECT
    D.SourceColumn
,   D.Description
FROM
(
    VALUES 
        (CAST('T' AS varchar(4)), 'T')
    ,   (CAST('R' AS varchar(4)), 'R')
    ,   (CAST('' AS varchar(4)), 'Empty string')
    ,   (CAST('    ' AS varchar(4)), 'Blanks')
    ,   (NULL, 'NULL')
) D (SourceColumn, Description);

Для моего поиска я ограничил приведенный выше запрос только строками T, R и пустой строки.

введите здесь описание изображения

Вы можете видеть, что для 5 исходных строк T, R и Empty String совпали и перешли к пути Match Output. Там, где я использовал NULL или явно использовал пробелы, не совпало.

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

Что?

В режиме полного кэша преобразование «Уточняющий запрос» выполняет исходный запрос и сохраняет данные локально на компьютере, на котором выполняются службы SSIS. Этот поиск будет точным соответствием с использованием правил равенства .NET. В этом случае '' не будет соответствовать ' '.

Однако, когда мы изменим наш режим кэширования на None или Partial, мы больше не будем полагаться на правила сопоставления .NET и вместо этого будем использовать правила сопоставления исходной базы данных. В TSQL '' будет соответствовать ' '

Чтобы ваш режим полного кэша работал должным образом, вам нужно будет применить RTRIM к преобразованию «Источник» и/или «Уточняющий запрос». Если вы убеждены, что RTRIM не работает с вашим исходным кодом, добавьте преобразование производного столбца, а затем примените туда свой RTRIM, но я считаю, что лучше злоупотреблять базой данных, а не SSIS.

Бимл

Biml, язык разметки бизнес-аналитики, описывает платформу для бизнес-аналитики. Помощник по BIDS — это бесплатное дополнение для Visual Studio/BIDS/SSDT, которое мы собираемся использовать для преобразования файл Biml ниже в пакет SSIS.

Следующий biml сгенерирует

<Biml xmlns="http://schemas.varigence.com/biml.xsd">
    <Connections>
        <OleDbConnection Name="CM_OLE" ConnectionString="Data Source=localhost\dev2012;Initial Catalog=tempdb;Provider=SQLNCLI11.0;Integrated Security=SSPI;" />
    </Connections>
    <Packages>
        <Package ConstraintMode="Linear" Name="so_26719974">
            <Tasks>
                <Dataflow Name="DFT Demo">
                    <Transformations>
                        <OleDbSource 
                            ConnectionName="CM_OLE" 
                            Name="OLESRC Source">
                            <DirectInput>
                            SELECT
                                D.SourceColumn
                            ,   D.Description
                            FROM
                            (
                                VALUES 
                                    (CAST('T' AS varchar(4)), 'T')
                                ,   (CAST('R' AS varchar(4)), 'R')
                                ,   (CAST('' AS varchar(4)), 'Empty string')
                                ,   (CAST('    ' AS varchar(4)), 'Blanks')
                                ,   (NULL, 'NULL')
                            ) D (SourceColumn, Description);
                            </DirectInput>
                        </OleDbSource>
                        <Lookup 
                            Name="LKP POC"
                            OleDbConnectionName="CM_OLE"
                            NoMatchBehavior="RedirectRowsToNoMatchOutput"
                            >
                            <DirectInput>
                            SELECT
                                D.SourceColumn
                            FROM
                            (
                                VALUES 
                                    (CAST('T' AS varchar(4)))
                                ,   (CAST('R' AS varchar(4)))
                                ,   (CAST('' AS varchar(4)))
                            ) D (SourceColumn);
                            </DirectInput>
                            <Inputs>
                                <Column SourceColumn="SourceColumn" TargetColumn="SourceColumn"></Column>
                            </Inputs>
                        </Lookup>
                        <DerivedColumns Name="DER Default catcher" />
                        <DerivedColumns Name="DER NoMatch catcher">
                            <InputPath OutputPathName="LKP POC.NoMatch" />
                        </DerivedColumns>
                    </Transformations>

                </Dataflow>
            </Tasks>
        </Package>
    </Packages>
</Biml>
person billinkc    schedule 03.11.2014
comment
Спасибо за подробный ответ и объяснение того, чем режимы кэширования отличаются друг от друга (.NET и T-SQL). Проблема была на входе, я добавил преобразование производного столбца, применив RTRIM к затронутому столбцу, и все заработало нормально. Однако я до сих пор не понимаю, почему это происходит: если я запускаю этот запрос в SSMS: SELECT Clave, LEN(Clave) FROM ..., я получаю длину 0 для всех строк с пустой строкой Clave. Clave это VARCHAR(4) на столе. Я использую источник OLE DB, который напрямую читает таблицу и несколько добавляет конечные пробелы. Этому есть объяснение? - person JotaBe; 04.11.2014
comment
Я отвечаю сам себе... Если я повторяю запрос, добавляя 'M' + Clave + 'M', я вижу, что там действительно есть пробел, даже если он говорит, что «LEN» равен 0. Глупый я, если я читаю документы для LEN: возвращает количество символов указанного строкового выражения, за исключением пробелов в конце. - person JotaBe; 04.11.2014
comment
Не возражаете, если я отредактирую ваш ответ и добавлю в него информацию об этом комментарии? - person JotaBe; 04.11.2014

Проблема в том, что FULL Cache использует сравнение на равенство .Net, а Partial и None используют SQL.
У меня была похожая проблема, когда все хорошо работает с Partial cache, и когда я использую Full, я получаю ошибки с Row not found, так как я терплю неудачу при отсутствии совпадений. Моя проблема заключалась в строке нижнего регистра в источнике и версии UPPER в таблице поиска, поэтому Full/.Net видит их как разные, а Partial/SQL с удовольствием выполняет соединение без учета регистра. Выведите строки «Нет совпадений» в CSV-файл, если вы хотите увидеть строки, в которых произошел сбой.

person JoeK    schedule 22.06.2017