2016-08-09 4 views
0

У меня есть набор полей (все символы) Я пишу к столу (new_table) из другой таблицы (old_table). Есть четыре поля in old_table - месяц, день, век, год (опять же, на черном). Я добавляю эти даты в new_table как одно поле - invdat (char). Клиент хотел бы добавить ведущие нули к дате, потому что они в настоящее время не хранятся в old_table.Добавить ведущие нули на операторе SQL INSERT

Вот пример:

INSERT INTO new_table 
SELECT month || oedy01 || oecc01 || oeyr01 || as invdat 
FROM old_table 

Таким образом, я должен был бы добавить ведущие нули в этих областях, прежде чем положить их в invdat поле в new_table.

Любые советы приветствуются.

+0

Первый вопрос: почему части даты хранятся как отдельные строки, а не одна дата? Второй вопрос - почему вы хотите построить из него строку, а не дату? Гораздо проще работать с датами при использовании типа даты. –

+0

В любом случае, вот как левые ноты для строки: http://stackoverflow.com/questions/4964244/pad-varchar-numbers-with-0s-in-db2 –

+4

Я бы попробовал некоторое обучение клиентов на вот этот. Даты сохраняются в «слое данных», пока они отображаются на «уровне представления». Уровень данных и формат, в котором они хранятся, не имеют никакого значения, когда дело доходит до отображения и заполнения. Echo of Thorsten, переключение на поля даты ... вы в настоящее время настраиваете полный беспорядок для своего клиента, чтобы иметь дело в более позднее время. – Twelfth

ответ

2

Существует множество причин, по которым система со старым программным обеспечением хранит даты в виде символьной строки. Скорее всего, это потому, что программное обеспечение было написано до даты, когда типы данных были легко доступны в RPG. В комментарии выше упоминается, что это было сделано таким образом в течение 20 лет. Вероятно, существует много кода, и его изменение для удовлетворения «новых» соглашений является дорогостоящим. Хотя DB2/400 и RPG IV обрабатывают даты сегодня довольно хорошо, кто хочет перекодировать и повторно протестировать большую систему, которая работает очень хорошо на протяжении десятилетий, когда есть еще одна работа, которая должна быть выполнена? Тем не менее, вот простой способ, с помощью AS/400-счастливого SQL DB2, нулевой площадки поля вашего в одном поле даты:

INSERT INTO new_table 
SELECT Right('00'||month,2) || Right('00'||oedy01,2) || Right('00'||oecc01,2) || Right('00'||oeyr01,2) as invdat 
FROM old_table 

Я предлагаю проверить эту формат дата с разработчиками AS/400. Как правило, вы увидите дату, сохраненную таким образом в формате ccyymmdd, но в этом нет жесткого и быстрого правила.

+0

Вот что они рассказали мне о датах, когда я спросил их. Они сказали назад, когда они начали (в начале 80-х) на кодовой базе, которую они все еще программировали в RPGIII. Но это решение работает отлично. Спасибо. – Echoic

2

По типичным, ОП не дал своего DDL.

FWiW, может быть большое преимущество в хранении отдельных компонентов дат, , если, большинство запросов зависит от этих компонентов и индексируются; хотя с дополнительной возможностью производного INDEX выражения, такие как YEAR (date_field) или SUBSTR (mmddyyyy_string_field, 5, 4) в качестве ключа, могут улучшить проблемы с выводами времени выполнения, для которых они выполняются. Преобразование в описанный INVDAT в выбранном формате - это не все, что хорошее выбора ИМО, даже если большинство из них не соответствуют конкретным компонентам даты; Я прокомментирую это позже.

Хотя можно было бы ожидать, что принятый ответ должен дать в целом правильные результаты из-за ожиданий о том, что область данных, являющихся явными значениями даты, по меньшей мере, одной цифрой [строка или числовая], результаты вполне зависят от данные-типирование; что за «начальные нули ... в настоящее время не хранятся» в старых значениях, тип данных является явно символьной строкой vs числовой, а для «(опять же, в char)» можно ожидать CHAR vs VARCHAR. И как строковые данные, нет упоминания о том, можно ли отрегулировать ненулевые запаздывающие \ добавленные сохраненные значения с помощью корректировки вправо или с правой стороны.

Это и другие \ будущих ответов и комментарии могут не подходить для фактического и неизвестного \ неустановленного DDL, и, таким образом, эти ответы должны быть предисловием эффективного «с этим DDL как данных»; но также и для типичных респондентов редко будут предлагать это пояснение :-(

Например, скаляр Left Pad (LPAD) [доступен с IBM DB2 for i 7.1], который уже упоминался в комментарии. более заметный соответствующий скалярный запрос для предполагаемого эффекта, чем использование более длинного существующего и вполне способного RIGHT-скаляра [в сочетании с добавлением строки из одного или нескольких нулей, что необходимо для фактических данных, которые также были оставлены в OP, но, безусловно, действительный только при объединении с лишенным значения], LPAD, вероятно, также не сработает для OP, потому что их исходные данные, скорее всего, CHAR [per "(опять же, char)"], а не VARCHAR , т.е. LPAD не соответствует здравому смыслу , за неудачу в реализации наиболее вероятных \ рациональных намерений и вместо этого работает как не более чем эффективная подстрока по данным CHAR фиксированной длины, несмотря на то, что функция SUBSTR уже давно существует для этого эффекта.

Конечно, с теми же выводами о том, что OP имеет для DDL, даже выражение RIGHT('00' CONCAT char_2_field, 2) не дает желаемых результатов; например с измененным по левому краю значением '1 ' в поле, это выражение эффективно запрашивает RIGHT(CHAR('001 ', 4), 2), для которого результат '1 ', а не предполагаемый желаемый '01' и с правильным значением ' 1' в поле, это выражение эффективно запрашивая RIGHT(CHAR('00 1', 4), 2), для которого результат ' 1', а не предполагаемый желаемый '01'. Я был на самом деле немного удивлен, что ответил; т. е. я был потрясен тем, что, по-видимому, исходный DDL имел поля, объявленные как VARCHAR, и что эти значения, по-видимому, также были правильно удалены, когда они были сохранены или надлежащим образом отброшены как таковые, откуда они пришли.

Если эти поля были VARCHAR или были выполнены STRIP [или LTRIM или аналогичными] для осуществления ввода данных различной строки [по-видимому, необязательно с левым урезанным результатом в соответствии с последствиями документов для эффекта LPAD, но мой опыт предполагает, что рекомендуется использовать левую или полностью зачистку], тогда строка может быть сгенерирована, как ожидалось, для выражений, предлагаемых как в ответе , так и в комментарии .

Скаляр DATE, отмеченный в комментарии, может быть опущен, и порядок компонентов даты может быть переупорядочен. Но в качестве строки вместо результата ввода данных DATE строка, отформатированная как MMDDYYYY, показанная в OP , нехорошо упорядоченная [лишена лексикографического качества], поэтому бесполезна при сортировке и селективности для чего угодно, кроме [ не] равные предикаты; строка, форматированная как YYYYMMDD [почти как то, что этот комментарий пытается предложить] :хорошо упорядоченный, поэтому он хорошо подходит для сортировки и для относительной [а не только совпадения | несовпадения] избирательности; не имея неотъемлемой поддержки для арифметики DATE и валидации, является меньшим отрицательным.

Примечание: следующие сценарии действий для DDL и заполняющих данных предполагают, что «cc» относится к простым двузначным значениям счетного века; т.е. «cc» игнорирует нулевой век, так что «19» подразумевает 1900-е годы, а не 1800-е, и такое, что «cc» не является альтернативным отображением таких «00» -> 19, 01 '-> 20' , и т.д..

Установки для обеспечения тестирования данных и альтернативных запросов:

create table old_table 
(month char(2) not null with default 
, oedy01 char(2) not null with default 
, oecc01 char(2) not null with default 
, oeyr01 char(2) not null with default 
) 
; 
create table new_table 
(invdat char(8) not null with default 
) 
; 
insert into old_table /* mm, dd, cc, yy */ values   
    (' 1', ' 1', '19', '40'), ('3 ', '3 ', '19', '40') 
, (' 1', ' 1', '20', ' 0'), ('3 ', '3 ', '20', '0 ') 
, (' 2', ' 2', '20', ' '), ('4 ', '4 ', '20', ' ') 
, (' 1', ' 1', '20', ' 1'), ('3 ', '3 ', '20', '1 ') 
, (' 1', ' 1', '20', '39'), ('3 ', '3 ', '20', '39') 
, (' 1', ' 1', ' 0', ' 1'), ('3 ', '3 ', '0 ', '1 ') 
, (' 2', ' 2', ' ', ' 1'), ('4 ', '4 ', ' ', '1 ') 
; -- mm(1,2):right-adj, mm(3,4):left-adj, mm(2,4):blank-elems 
    -- 14 rows inserted in OLD_TABLE 

Теперь для запросов, что была установка выше:

SELECT Right('00'||month, 2) || Right('00'||oedy01, 2)   
    || Right('00'||oecc01, 2) || Right('00'||oeyr01, 2) as invdat 
from old_table 
where month not in (2, 4) 
; -- report of above query follows; no leading zeroes anywhere: 
    INVDAT 
    1 11940 
    3 3 1940 
    1 120 0 
    3 3 200 
    1 120 1 
    3 3 201 
    1 12039 
    3 3 2039 
    1 1 0 1 
    3 3 0 1 
-- end of data -- 
select               
    lpad(month , 2, '0') concat lpad(oedy01, 2, '0') concat 
    lpad(oecc01 , 2, '0') concat lpad(oeyr01, 2, '0') as invdat 
from old_table             
where month not in (2, 4) 
; -- report of above query follows; no leading zeroes anywhere: 
    INVDAT 
    1 11940 
    3 3 1940 
    1 120 0 
    3 3 200 
    1 120 1 
    3 3 201 
    1 12039 
    3 3 2039 
    1 1 0 1 
    3 3 0 1 
-- end of data; a duplicate of the prior query report -- 

Так что с данной настройкой, указанные запросы не являются очень полезно. С несовершеннолетним пересмотр каждого запроса, чтобы обеспечить данные CHAR сначала раздели лишних пробелов, результаты намного лучше:

select      
    lpad(strip( month) , 2, '0') concat 
    lpad(strip( oedy01) , 2, '0') concat 
    lpad(strip( oecc01) , 2, '0') concat 
    lpad(strip( oeyr01) , 2, '0') as invdat 
from old_table        
/* where month not in (2, 4) -- this *fixes* blank values too */ 
; -- report of above query follows; expected leading zeroes appear: 
    INVDAT 
    01011940 
    03031940 
    01012000 
    03032000 
    02022000 
    04042000 
    01012001 
    03032001 
    01012039 
    03032039 
    01010001 
    03030001 
    02020001 
    04040001 
-- end of data -- 
SELECT            
    Right('00' concat strip(month) , 2) concat 
    Right('00' concat strip(oedy01) , 2) concat 
    Right('00' concat strip(oecc01) , 2) concat 
    Right('00' concat strip(oeyr01) , 2) as invdat 
from old_table          
/* where month not in (2, 4) -- this *fixes* blank values too */ 
; -- report of above query matches the prior; not repeated here 

Если DDL были вместо числовых и известно, имеют действительные данные десятичные, сохраненные для значений, то следующий может быть представитель сценария:

drop table old_table 
; 
create table old_table     
(month dec (2) not null with default 
, oedy01 dec (2) not null with default 
, oecc01 dec (2) not null with default 
, oeyr01 dec (2) not null with default 
)          
; 
insert into old_table /* mm, dd, cc, yy */ values   
    (' 1', ' 1', '19', '40'), ('3 ', '3 ', '19', '40') 
, (' 1', ' 1', '20', ' 0'), ('3 ', '3 ', '20', '0 ') 
, (' 1', ' 1', '20', ' 1'), ('3 ', '3 ', '20', '1 ') 
, (' 1', ' 1', '20', '39'), ('3 ', '3 ', '20', '39') 
, (' 1', ' 1', ' 0', ' 1'), ('3 ', '3 ', '0 ', '1 ') 
; -- notably, no blank values per inability to cast to decimal 
select 
    digits(month) concat digits(oedy01) concat 
    digits(oecc01) concat digits(oeyr01) as invdat 
from old_table          
; -- report from above query follows; DIGITS casting gives leading zeros: 
INVDAT 
01011940 
03031940 
01012000 
03032000 
01012001 
03032001 
01012039 
03032039 
01010001 
03030001 
-- end of data -- 

Оба запросов предложенных [вариантов, которые я включил в моих примерах выше; один с выражением RIGHT(), и тот, который имеет LPAD()] из ответа и в комментарии , даст тот же отчет, что и выше. Это связано с тем, что результатом неявного переноса из CHAR в DECIMAL является измененное по левому краю переменное символьное строковое представление числового значения и, следовательно, неявно левая и изменяемая длина, поэтому эти скалярные функции будут давать желаемый результат.

Если вышеописанный скрипт для использования числовых типов данных [вместо «ссылались весь полукокс» типов данных] является причиной ответа выбран ОРОМ как приемлемые, то, что служит, чтобы подчеркнуть, как poorly- объяснил сценарий проблемы, и подразумевает, насколько легко это могло быть предотвращено, включив DDL; и лучше, чтобы дополнительно включить образцы данных.

Смежные вопросы