зацикливание оператора вставки SQL с датами - PullRequest
0 голосов
/ 25 февраля 2011

Мне нужно запустить оператор, который будет заполнять базу данных одной и той же информацией каждый раз, ИСКЛЮЧИТЬ дату.

В настоящее время я пытаюсь что-то сделать в этом направлении и не везет.

DECLARE 
i_int BINARY_INTEGER := 1;
  BEGIN
    WHILE i_int <= 30 LOOP
      INSERT INTO bs_events (eventDate,eventTime,title,spaces,description,entryFee,payment_required,max_qty,allow_multiple) VALUES ('2011-03-i_int 00:00:00', '10:00','Carpet Cleaner 3000','4','This is rad','25.99','1','1','2');
      i_int := i_int + 1;
    END LOOP;
  END;
  /

Мне не удается заставить его работать, и я застрял в дыре в коде и не могу думатьпрямо.

В основном я хочу, чтобы дата была на единицу больше с 01-30, а затем я вручную изменил бы месяц и снова запустил сценарий для всех 12 месяцев года.

Ответы [ 4 ]

4 голосов
/ 26 февраля 2011

Рассмотрите возможность создания календарной таблицы .

Первая таблица, которую я создаю в любой базе данных, с которой я работаю, это таблица чисел от 1 до 1000000. Такая таблица полезна для многих целей, таких как реализация циклов в SQL. Кроме того, его можно использовать для создания второй таблицы, которую я создаю, в любой базе данных, с которой я работаю: Таблица «Календарь».

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

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

Я приведу вам тривиальный, но работающий пример в MySQL ниже:

create table digits(n int);
insert into digits values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);

create table numbers(
   n int not null
  ,primary key(n)
);

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

insert 
  into numbers(n)
select 1 
      + (d1.n * 1)
      + (d2.n * 10)
      + (d3.n * 100)
      + (d4.n * 1000)
      + (d5.n * 10000)
      + (d6.n * 100000) as n
  from digits d1
      ,digits d2
      ,digits d3
      ,digits d4
      ,digits d5
      ,digits d6;

/* Drop the working table. */
drop table digits;

Далее я создам таблицу календаря. Очевидно, что в данный момент он совершенно бесполезен, поскольку в нем нет полезных столбцов. Примерами полезных столбцов являются год, имя месяца, номер недели, isFirstMonthDay, isLastMonthDay, финансовый год, isHoliday, праздничное имя, имя дня, квартал, tertial. Для нестандартных периодов это золото.

create table calendar(
   datum date not null
  ,primary key(datum)
);

Хорошо, теперь мы можем использовать таблицу чисел, например, в качестве генератора строк для построения нашей календарной таблицы. Допустим, я хочу сгенерировать все даты между 2000-01-01 и 2019-12-31. Это было бы 7305 дней. Легко, просто выберите столько строк из таблицы чисел и добавьте столбец int N к дате. Это создаст список возрастающих дат.

insert 
  into calendar(datum)
select date_add('1999-12-31', interval n day)
  from numbers
 where n <=7305;

Готово. Возможно, вы могли бы увидеть, как вы могли бы решить свою проблему, просто используя таблицу чисел?

Наконец, вот пример того, как решить вашу конкретную проблему с помощью таблицы календаря. Конечно, было бы еще проще, если бы вы добавили столбцы для года и месяца. Здесь я интерпретирую ваш вопрос как «Создайте одну одинаковую строку для каждого дня каждого месяца, для остальной части года».

insert 
  into bs_events(
        eventDate,        eventTime,      title
       ,spaces,           description,    entryFee
       ,payment_required, max_qty,        allow_multiple
       )
 select datum,            '10:00',        'Carpet Cleaner 3000'
       ,'4',              'This is rad',  '25.99'
       ,'1',              '1',            '2'
   from calendar
  where datum >= date '2011-03-01'
    and datum <= date '2011-12-31';
1 голос
/ 25 февраля 2011

Вы можете попробовать DATEADD(ms,i_int,GETDATE()) для вашей даты.

0 голосов
/ 25 февраля 2011
DECLARE 
i_int BINARY_INTEGER := 0;
  BEGIN
    WHILE i_int < 30 LOOP
      INSERT INTO bs_events (
        eventDate, eventTime, title,
        spaces, description, entryFee,
        payment_required, max_qty, allow_multiple)
      VALUES (
        DATEADD(day, i_int, '2011-03-01 00:00:00'), '10:00', 'Carpet Cleaner 3000',
        '4', 'This is rad', '25.99',
        '1', '1', '2');
      i_int := i_int + 1;
    END LOOP;
  END;
  /
0 голосов
/ 25 февраля 2011
INSERT INTO bs_events (eventDate, ... ) 
VALUES ('2011-03-i_int 00:00:00', ...);

Это значение, 2011-03-i_int 00:00:00, является строкой, а не отметкой времени.Вы надеялись, что ваша среда SQL заменит значение символа i_int.Это не будет сделано.

Вместо этого сделайте арифметику даты вне оператора INSERT.

В PostgreSQL (PL / pgsql) вы можете сделать это, чтобы добавить день в переменную типа'timestamp'.

this_date = this_date + interval '1 day';

А в операторе INSERT

INSERT INTO bs_events (eventDate, ... ) 
VALUES (this_date, ...);

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

...