Список форумов BOSSForum.RU - Форум. БОСС-Кадровик
Независимый форум, посвященный системе БОСС-Кадровик
и всему, что с ней связано
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 

Кавычка, взорвавшая мозг :)))

 
Начать новую тему   Ответить на тему    Список форумов BOSSForum.RU - Форум. БОСС-Кадровик -> X-язык
Предыдущая тема :: Следующая тема  
Автор Сообщение
zhenya17



Зарегистрирован: 04.02.2009
Сообщения: 190
Откуда: Кемерово

СообщениеДобавлено: Вт Фев 14, 2012 07:20    Заголовок сообщения: Кавычка, взорвавшая мозг :))) Ответить с цитатой

Есть небольшая x-процедура. Весь текст приводить не буду, остановлюсь на ключевом. В процедуру передаётся несколько параметров, в том числе, переменная ldate__ - дата увольнения сотрудника. Мне нужно было добавить небольшую проверку, но не тут-то было... В процедуре поле ldate__ используется много раз и имеет некоторое значение, допустим, '2012-01-14'. Но! Экспериментальным путём удалось установить, что когда выполняется условие "IF NextDate > ldate__", то из ldate__ куда-то девается кавычка, т.е. return 2 выдаёт '2012-02-14', а return 3 - '2012-02-14. Из-за этого, естественно, последующие sql-запросы выдают ошибку.
Мой мозг взорван... Может, кто-то видит что-то криминальное в строке между ретурнами №2 и №3? Вообще не представляю, в каком направлении копать Sad

Код:
      ALIAS BegMonth == fdate__;
      WHILE (BegMonth <= ldate__) THEN {
return 1: ldate__;
        SELECT dateadd(day,-1,dateadd(month, 1, BegMonth)) INTO NextDate;
return 2: ldate__;
        IF NextDate > ldate__ THEN LOCAL NextDate == ldate__;
return 3: ldate__;
        SELECT datediff(day,BegMonth,dateadd(day,1,NextDate)) INTO MonthDays;
--        SELECT isnull(Max(d), convert(datetime,ldate__,104))
        SELECT isnull(Max(d),'1900-01-01')
          Into EndMonth
          From (Select Top MonthDays d from #LS_CALEND where d >= BegMonth order by d) as cal;
if EndMonth = '1900-01-01' then alias EndMonth == ldate__;
-- Корректировка дней MonthDays на неявки
        SELECT Count(*)
          Into MonthDays
          From (Select Top MonthDays d from #LS_CALEND where d >= BegMonth order by d) as cal;
--return BegMonth,EndMonth,MonthDays,  fdate__, ldate__;
        SELECT
          (CASE WHEN FROMD < BegMonth THEN BegMonth ELSE FROMD END),
          (CASE WHEN TOD > EndMonth THEN EndMonth ELSE TOD END),
          CAST(STRING AS INTEGER)
          INTO PrivilegeBegin, PrivilegeEnd, PrivilegeValue
          FROM PR_GROUP_VALUE
          WHERE ID_GROUP = IdGroup AND ID_REF = AutoCard AND FROMD <= EndMonth AND TOD >= BegMonth;
       
        SELECT COUNT(*)
          INTO PrivilegeDay
          From (Select Top MonthDays d from #LS_CALEND where d >= PrivilegeBegin and  d <= PrivilegeEnd order by d) as cal;
       
        Let LeaveDaysMonth = 0.00;
      IF comp_out_flg_ = 1 THEN {
          IF MonthDays > 15 THEN {
            IF PrivilegeDay > 15 THEN Let LeaveDaysMonth = Round(PrivilegeValue*1.00/12,2)
            ELSE Let LeaveDaysMonth = Round(LeaveDaysConst*1.00/12,2);
            Let LeaveDays = LeaveDays + LeaveDaysMonth;
          };
        }
        ELSE {
          IF PrivilegeDay > 15 THEN Let LeaveDaysMonth = Round(PrivilegeValue*1.00/12,2)
          ELSE Let LeaveDaysMonth = Round(LeaveDaysConst*1.00/12,2);
          Let LeaveDays = LeaveDays + LeaveDaysMonth;
        };
--> $LS Excel
  IF ShowExcel = 1 THEN {
        Let Absence = datediff(day,BegMonth,EndMonth)-MonthDays+1;
        Excel.Cells(Row, 1).Value = MonthCount;
        Excel.Cells(Row, 2).Value = BegMonth;
        Excel.Cells(Row, 3).Value = EndMonth;
        Excel.Cells(Row, 4).Value = MonthDays;
        IF Absence > 0 THEN Excel.Cells(Row, 5).Value = Absence;
        IF PrivilegeDay > 0 THEN Excel.Cells(Row, 6).Value = PrivilegeDay;
        IF PrivilegeValue > 0 THEN Excel.Cells(Row, 7).Value = PrivilegeValue;
        IF LeaveDaysMonth > 0 THEN Excel.Cells(Row, 8).Value = LeaveDaysMonth;

        Let MonthCount = MonthCount + 1;
        Let Row = Row + 1;
  };
--< $LS Excel
        SELECT dateadd(day, 1, EndMonth) INTO BegMonth;
return 4: ldate__;
      }; --WHILE
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
vladimir22



Зарегистрирован: 14.01.2010
Сообщения: 21

СообщениеДобавлено: Вт Фев 14, 2012 14:41    Заголовок сообщения: Ответить с цитатой

Не, мозг взорван раньше.
Это последствия Smile

А какой смысл Вы вкладываете в оператор:

IF NextDate > ldate__ THEN LOCAL NextDate == ldate__;

Причем как в слово "LOCAL" в даном контексте, так и в оператор "==" ?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
RVV
Большой шоколадный орден
Большой шоколадный орден


Зарегистрирован: 14.01.2010
Сообщения: 449

СообщениеДобавлено: Вт Фев 14, 2012 15:58    Заголовок сообщения: Ответить с цитатой

А я всегда думал, что присвоение в операторе ALIAS пишется через :=
а не так
ALIAS BegMonth == fdate__;

чудо, что этот код вообще работает ...
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Mike
Большой шоколадный орден
Большой шоколадный орден


Зарегистрирован: 07.04.2011
Сообщения: 255

СообщениеДобавлено: Вт Фев 14, 2012 17:13    Заголовок сообщения: Ответить с цитатой

RVV писал(а):
А я всегда думал, что присвоение в операторе ALIAS пишется через :=
а не так
ALIAS BegMonth == fdate__;

чудо, что этот код вообще работает ...


еще "=" можно =)
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
zhenya17



Зарегистрирован: 04.02.2009
Сообщения: 190
Откуда: Кемерово

СообщениеДобавлено: Ср Фев 15, 2012 07:44    Заголовок сообщения: Ответить с цитатой

Что касается чудо-строчки IF NextDate > ldate__ THEN LOCAL NextDate == ldate__;, то я в неё никакой смысл не вкладывала, т.к. изначально код не мой. Но понятно, что эту строчку я рассматривала очень пристально Smile
На самом деле, в зависимости от того, стоит в ней "Local", "Let", "Alias" или просто приравнивание, а также в зависимости от знаков "=", "==" или ":=" в NextDate тоже то появляется, то исчезает кавычка, либо выдаётся программная ошибка Smile))
В том-то и дело, что я не могу найти какой-то логической зависимости... Могу только привести полный код процедуры
Код:
(pId__, fdate__, ldate__, comp_out_flg_ = 0, ShowExcel = 0);
  LOCAL LeaveDays = 0.00;
  IF OBJECT_ID('TEMPDB..#LS_CALEND') IS NOT NULL THEN DROP TABLE #LS_CALEND;
  $SELECT CALEND.D INTO #LS_CALEND FROM (SELECT D FROM Z_CALEND GROUP BY D) AS CALEND
    WHERE CALEND.D BETWEEN fdate__[''] AND ldate__[''];

  SELECT SUM(DATEDIFF(DAY,(CASE WHEN FROMD < fdate__[''] THEN fdate__[''] ELSE FROMD END),(CASE WHEN TOD > ldate__[''] THEN ldate__[''] ELSE TOD END)) + 1)
    INTO AdmDays
    FROM PR_LEAVE 
    WHERE OPERAT = 5 AND PID = pId__ AND FROMD <= ldate__[''] AND TOD >= fdate__[''];

  IF AdmDays > 14 THEN
    DELETE #LS_CALEND
    FROM #LS_CALEND, PR_LEAVE
    WHERE #LS_CALEND.D BETWEEN PR_LEAVE.FROMD AND PR_LEAVE.TOD
      AND PR_LEAVE.OPERAT IN (3, 5, 7)
      AND PR_LEAVE.PID = pId__
      AND PR_LEAVE.TOD >= fdate__['']
  ELSE
    DELETE #LS_CALEND
    FROM #LS_CALEND, PR_LEAVE
    WHERE #LS_CALEND.D BETWEEN PR_LEAVE.FROMD AND PR_LEAVE.TOD
      AND PR_LEAVE.OPERAT IN (3, 7)
      AND PR_LEAVE.PID = pId__
      AND PR_LEAVE.TOD >= fdate__[''];

  DELETE #LS_CALEND
  FROM #LS_CALEND, PR_WALK, TYP_ABSENCE
  WHERE #LS_CALEND.D BETWEEN PR_WALK.FROMD AND PR_WALK.TOD
    AND TYP_ABSENCE.CODE_ABSENCE = PR_WALK.CODE_ABSENCE
    AND TYP_ABSENCE.SWITCH_ON = 1
    AND PR_WALK.PID = pId__
    AND PR_WALK.TOD >= fdate__[''];

  SELECT COUNT(*) FROM #LS_CALEND INTO PerDays;

  IF ExistsPrivilege = 0 AND comp_out_flg_ = 0 THEN {
     Let LeaveDays = LeaveDaysConst;
--> $LS Excel
  IF ShowExcel = 1 THEN {
      Let Absence = datediff(day,fdate__,ldate__)-PerDays+1;
      Excel.Cells(Row, 1).Value = 1;
      Excel.Cells(Row, 2).Value = fdate__;
      Excel.Cells(Row, 3).Value = ldate__;
      Excel.Cells(Row, 4).Value = PerDays;
      Excel.Cells(Row, 5).Value = Absence;
      Excel.Cells(Row, 8).Value = LeaveDays;
      Let Row = Row + 1;
  };
--< $LS Excel
  }
  ELSE {
    IF ExistsAllPeriod = 1 AND comp_out_flg_ = 0 THEN {
      SELECT TOP 1 CAST(STRING AS INTEGER) INTO LeaveDays FROM PR_GROUP_VALUE
      WHERE ID_GROUP = IdGroup AND ID_REF = AutoCard AND FROMD <= ldate__ AND TOD >= fdate__;
--> $LS Excel
  IF ShowExcel = 1 THEN {
      Let Absence = datediff(day,fdate__,ldate__)-PerDays+1;
      Excel.Cells(Row, 1).Value = 1;
      Excel.Cells(Row, 2).Value = fdate__;
      Excel.Cells(Row, 3).Value = ldate__;
      Excel.Cells(Row, 4).Value = PerDays;
      Excel.Cells(Row, 5).Value = Absence;
      Excel.Cells(Row, 6).Value = PerDays;
      Excel.Cells(Row, 7).Value = LeaveDays;
      Excel.Cells(Row, 8).Value = LeaveDays;
      Let Row = Row + 1;
  };
--< $LS Excel
    }
    ELSE {
      ALIAS BegMonth == fdate__;
      WHILE (BegMonth <= ldate__) THEN {
return 1: ldate__;
        SELECT dateadd(day,-1,dateadd(month, 1, BegMonth)) INTO NextDate;
return 2: ldate__, NextDate;
--      IF NextDate > ldate__ THEN LOCAL NextDate == ldate__;
        IF NextDate > ldate__ THEN ALIAS NextDate == ldate__;
return 3: ldate__, NextDate;
        SELECT datediff(day,BegMonth,dateadd(day,1,NextDate)) INTO MonthDays;
--        SELECT isnull(Max(d), convert(datetime,ldate__,104))
        SELECT isnull(Max(d),'1900-01-01')
          Into EndMonth
          From (Select Top MonthDays d from #LS_CALEND where d >= BegMonth order by d) as cal;
if EndMonth = '1900-01-01' then alias EndMonth == ldate__;
-- Корректировка дней MonthDays на неявки
        SELECT Count(*)
          Into MonthDays
          From (Select Top MonthDays d from #LS_CALEND where d >= BegMonth order by d) as cal;
--return BegMonth,EndMonth,MonthDays,  fdate__, ldate__;
        SELECT
          (CASE WHEN FROMD < BegMonth THEN BegMonth ELSE FROMD END),
          (CASE WHEN TOD > EndMonth THEN EndMonth ELSE TOD END),
          CAST(STRING AS INTEGER)
          INTO PrivilegeBegin, PrivilegeEnd, PrivilegeValue
          FROM PR_GROUP_VALUE
          WHERE ID_GROUP = IdGroup AND ID_REF = AutoCard AND FROMD <= EndMonth AND TOD >= BegMonth;
       
        SELECT COUNT(*)
          INTO PrivilegeDay
          From (Select Top MonthDays d from #LS_CALEND where d >= PrivilegeBegin and  d <= PrivilegeEnd order by d) as cal;
       
        Let LeaveDaysMonth = 0.00;
      IF comp_out_flg_ = 1 THEN {
          IF MonthDays > 15 THEN {
            IF PrivilegeDay > 15 THEN Let LeaveDaysMonth = Round(PrivilegeValue*1.00/12,2)
            ELSE Let LeaveDaysMonth = Round(LeaveDaysConst*1.00/12,2);
            Let LeaveDays = LeaveDays + LeaveDaysMonth;
          };
        }
        ELSE {
          IF PrivilegeDay > 15 THEN Let LeaveDaysMonth = Round(PrivilegeValue*1.00/12,2)
          ELSE Let LeaveDaysMonth = Round(LeaveDaysConst*1.00/12,2);
          Let LeaveDays = LeaveDays + LeaveDaysMonth;
        };
--> $LS Excel
  IF ShowExcel = 1 THEN {
        Let Absence = datediff(day,BegMonth,EndMonth)-MonthDays+1;
        Excel.Cells(Row, 1).Value = MonthCount;
        Excel.Cells(Row, 2).Value = BegMonth;
        Excel.Cells(Row, 3).Value = EndMonth;
        Excel.Cells(Row, 4).Value = MonthDays;
        IF Absence > 0 THEN Excel.Cells(Row, 5).Value = Absence;
        IF PrivilegeDay > 0 THEN Excel.Cells(Row, 6).Value = PrivilegeDay;
        IF PrivilegeValue > 0 THEN Excel.Cells(Row, 7).Value = PrivilegeValue;
        IF LeaveDaysMonth > 0 THEN Excel.Cells(Row, 8).Value = LeaveDaysMonth;

        Let MonthCount = MonthCount + 1;
        Let Row = Row + 1;
  };
--< $LS Excel
        SELECT dateadd(day, 1, EndMonth) INTO BegMonth;
return 4: ldate__;
      }; --WHILE
    ); --ELSE {
  }; --ELSE {
};
break LeaveDays;


Процедура служит для расчёта дней коменсации при увольнении. Точнее, у нас сделана удобная Excel-форма, в которую выводится детализация расчёта, чтобы можно было понять, откуда взялось количество дней. Процедура была написана в 2007г. и работает стабильно кроме одного случая: глюк возникает, если у человека есть отпуск без сохранения з/п в день увольнения.
Например, товарищ взял отпуск без сохранения з/п с 1 по 5.02.2012г. и 5.02.2012г. увольняется. В этом случае при расчёте компенсации вылезет ошибка. Просто до этого кадровиков просили, чтобы они делали отпуск на 1 день покороче, а в табеле вручную проставляли код "ДО"в последний рабочий день. Но это же неудобно, хочется довести до ума...
У меня есть ещё мысли, с какой стороны зайти. Но просто про эту кавычку всё равно интересно, т.к. не могу понять, что к чему Sad
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
vladimir22



Зарегистрирован: 14.01.2010
Сообщения: 21

СообщениеДобавлено: Ср Фев 15, 2012 13:54    Заголовок сообщения: Ответить с цитатой

Доргая zhenya17 !

Не имеет абсолютно никакого значения что делает процедура Smile

Просто строка, на которую Вам указали в начале поста и которая вызывает ошибку - это БРЕД.
Поэтому и быз задан вопрос - каков смысл этой строки, что собственно она должна делать ?
Чтобы было понятно что подсказать как ее переписать.

Было написано:
IF NextDate > ldate__ THEN LOCAL NextDate == ldate__;

сейчас Вы переписали на:
IF NextDate > ldate__ THEN ALIAS NextDate == ldate__;

Но, понимаете ли, это что в лоб, что полбу.
Опять не попали Smile

Поясню свое впечателение от этой строки.
Во-первых, знак "==" - это логическое сравнение.
Что он должен делать в случае объявления новой переменной (что по ALIAS что по LOCAL) ?
Во-вторых, У Вас объявляется новая переменная NextDate. А как она соотносится с переменной с тем же именем в операторе сравнения слева ? Тем более что время жизни такой переменной в случае LOCAL вообще ограничено текущим блоком (от оператора THEN до конца строки) ?

Может должно быть написано что-то типа:

IF NextDate[''] > ldate__[''] THEN Let NextDate = ldate__[''];

???????????
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
zhenya17



Зарегистрирован: 04.02.2009
Сообщения: 190
Откуда: Кемерово

СообщениеДобавлено: Чт Фев 16, 2012 11:11    Заголовок сообщения: Ответить с цитатой

vladimir22, спасибо, что не оставляете меня без надежды на спасение Smile

vladimir22 писал(а):
Просто строка, на которую Вам указали в начале поста и которая вызывает ошибку - это БРЕД.
Поэтому и быз задан вопрос - каков смысл этой строки, что собственно она должна делать ?
Чтобы было понятно что подсказать как ее переписать.
По моей логике, с точки зрения программирования, эта строка тоже кажется бредовой. Хотя бы уже потому, что перед ней идёт Select, который запихивает значение в эту переменную, поэтому назначение Local мне непонятно. Я разобралась в логичекой части алгоритма и понимаю, что делается в процедуре и в этой строке, но я не знаю, о чём думал человек, написавший "Local". В частности, из-за этого я и начала экспериментировать с этой строкой.

vladimir22 писал(а):
Было написано:
IF NextDate > ldate__ THEN LOCAL NextDate == ldate__;

сейчас Вы переписали на:
IF NextDate > ldate__ THEN ALIAS NextDate == ldate__;

Но, понимаете ли, это что в лоб, что полбу.
Опять не попали Smile
Не совсем так. Я понимаю, что в данном случае что алиас, что локал должно быть "что в лоб, что по лбу". Поэтому я не написала алиас, я просто пробовала различные варианты: с local, с alias, с Let и просто без ключевого слова, в том числе, меняла и знаки присвоения. К сожалению, у меня нет в голове чёткой картинки, что если написать так-то, то проблема будет решена. есть лишь то, что описано в руководстве по "БОСС-Дизайнеру".

vladimir22 писал(а):
Может должно быть написано что-то типа:
IF NextDate[''] > ldate__[''] THEN Let NextDate = ldate__[''];
???????????
Вариант с кавычками я тоже пробовала Smile В частности, предложенный Вами вариант возвращает в ретурне№3 дату ldate__ с кавычками, а NextDate - без кавычек, поэтому злополучную строку мы проходим, а дальше рубимся на следующей же строке - sql-запросе, т.к. он получается следующего содержания:
Код:
SELECT isnull(Max(d),'1900-01-01') From (Select Top -38932 d from #LS_CALEND where d >= '2012-01-24' order by d) as cal


Если попробовать более логичную, на мой взгляд, конструкцию IF NextDate[''] > ldate__[''] THEN Let NextDate[''] = ldate__[''], то мы проходим и нашу злополучную строку, и последующий sql-запрос, но потом опять рубимся на кавычке, но уже в другом месте. И так какой-то замкнутый круг...

Согласна с RVV в одном:
RVV писал(а):
чудо, что этот код вообще работает ...

А хочется сделать так, чтобы это было не чудом, а закономерностью! Но победить эти 137 строчек кода пока что получается Crying or Very sad


Последний раз редактировалось: zhenya17 (Чт Фев 16, 2012 11:14), всего редактировалось 1 раз
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
vladimir22



Зарегистрирован: 14.01.2010
Сообщения: 21

СообщениеДобавлено: Чт Фев 16, 2012 11:11    Заголовок сообщения: Ответить с цитатой

Хотя, прощу прощения, страшие товарищи меня переубедили, что так писать можно и даже как-то должно работать.

Имеется в виду:

IF NextDate > ldate__ THEN ALIAS NextDate == ldate__;

а вот с вариантом:
IF NextDate > ldate__ THEN LOCAL NextDate == ldate__;

поосторожнее.
Таам как минимум создается вторая переменная NextDate.
Вы именно этого хотели в первоначальном варианет алгоритма ?

Только не понятно зачем так вообще писать.
См. предложенный вариант с Let.
Если заменить на него ошибка остается ?
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
zhenya17



Зарегистрирован: 04.02.2009
Сообщения: 190
Откуда: Кемерово

СообщениеДобавлено: Чт Фев 16, 2012 11:18    Заголовок сообщения: Ответить с цитатой

Про вариант с Let написала выше. Мы писали сообщения почти одновременно, воможно, Вы не видели предыдущего поста.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
zhenya17



Зарегистрирован: 04.02.2009
Сообщения: 190
Откуда: Кемерово

СообщениеДобавлено: Чт Фев 16, 2012 11:21    Заголовок сообщения: Ответить с цитатой

Кстати, самое фиговое, что я победила этот код 26.01.2012г, о чём сделала пометку в списке своих задач. Но поскольку сейчас идут всякие активные разработки, то, походу, забыла перенести изменения с тестовой на реальную базу. А второй раз на меня озарение никак не находит Laughing
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
vladimir22



Зарегистрирован: 14.01.2010
Сообщения: 21

СообщениеДобавлено: Чт Фев 16, 2012 15:12    Заголовок сообщения: Ответить с цитатой

Тогда надо смотрть по трассировку.
Поскольку функция написана так, что ее работа зависит не только о явно передаваемых параметров, но и от переменных, созданных где-то снаружи то только по ее тексту сказать что не так может оказаться невозможно.

Но в любом случае - трассирова Вам в руки.
Если предложенный мною запрос возвращает NextDate без кавычек - то действительно либо надо все тело функции переписать так, чтобы датные переменные на зависели от наличия или отсутствия кавычек - т.е. с маской [''].

Или в моем примере дописать AS DATE:
IF NextDate[''] > ldate__[''] THEN Let NextDate = ldate__[''] AS DATE;
Тогда тип переменной NextDate останется "date" и на везде сразу будет подставляться с кавычками.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Показать сообщения:   
Начать новую тему   Ответить на тему    Список форумов BOSSForum.RU - Форум. БОСС-Кадровик -> X-язык Часовой пояс: GMT + 4
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Pоwerеd by рhpВB © 2001, 2005 рhpВB Grouр
Русская поддержка phрВB
Rambler's Top100 Рейтинг@Mail.ru Список форумов BOSSForum.RU