Имя: Пароль:
1C
1C 7.7
v7: Что за проблема в Sqlite с укладкой отрицательных чисел, методом УложитьТЗ?
0 FobusVGrunt
 
13.06.16
20:52
Всем привет, а что за беда в Sqlite с выборкой отрицательных чисел, Улаживаю ТЗ-ку в базу Sqlite, с типизированными колонками как число. В самой базе хранится нормально с минусом. Делаю запрос на выборку вместо (-2226062580) получаю (2068904716). Дальше еще интересно, в БД  в ручную убрал минус, выдал запрос нормально  получил правильно(2226062580). Потом опять поставил минус в ручную, начало выбирать правильно (-2226062580). Потом повторно уложил методом УложитьТЗ, опять неправильно. При  укладки колонка в ТЗ (тип Число, 19,2), пробовал. Просто «Число», ничего не помогает
1 FobusVGrunt
 
13.06.16
20:59
(0) При выборке тоже перепробовал [... $Число.19.2] и так  [... $Число]. Зашел опять в ручную убрал, поставил минус, выбирает правильно. Дело походу в методе УложитТЗ
2 FobusVGrunt
 
13.06.16
21:07
(0) Если при укладки ТЗ, делать тип колонки не число, а строка, а при выборке делать типизацию $Число, тогда нормуль
3 Djelf
 
13.06.16
22:03
(0) Дело не совсем в методе уложить тз...
Читай тут https://www.sqlite.org/datatype3.html
Сравни
SELECT -2226062580
SELECT -2226062580.0
SELECT '-2226062580'
SELECT cast(-2226062580 AS double)
Это не баг, это фича ;)
4 FobusVGrunt
 
14.06.16
10:12
(3) Что-то не совсем понял, физически в таблице лежит правильно (-2226062580), не с 1С в запросе выбирает правильно. Если в ручную пересохранить значение и в 1С начинает правильно выбирать.
5 FobusVGrunt
 
14.06.16
11:06
(3) Попробовал в 1С:
"SELECT -2147483648 as Сумм,2147483648 as Сумм2,-2147483647 as Сумм3,'-2147483648' as Сумм4,cast(-2147483648 AS double) as Сумм5 ":
https://www.dropbox.com/s/xb3gmb45buvpis4/1C%20Test.jpg?dl=0
не в 1С:
https://www.dropbox.com/s/sugs26a7hq4mioa/SQLiteExspert.jpg?dl=0
6 FobusVGrunt
 
14.06.16
11:07
В (5)  видно, что дело в выборке, но по чему если перезаписать значение в таблице БД, начинает работать нормально.
7 FobusVGrunt
 
14.06.16
11:12
Djelf, скажи как лучше поступать, когда улаживаешь ТЗ в БД, вместо типа колонки "Число", указывать "Строка". Или преобразовывать при выборке с помощью cast?
И я так понимаю с числами <-2 147 483 648 и > 2 147 483 647 (с типом больше long int), в Sqlite надо работать осторожней
8 Djelf
 
14.06.16
13:02
(3) Физически оно как целое число должно хранится. Ты же сам заметил что когда оно строка или дробное ничего странного не происходит.
(7) Тебе же для перетаскивания данных оно надо? Значит  компактность не сильно то и нужна. Кидай строками - не придется голову ломать почему что-то не так.
9 FobusVGrunt
 
14.06.16
13:11
(8) Да для переноса, ок буду улаживать как строки, спасибо
10 Gary417
 
14.06.16
13:32
разлаживать, улаживать... блин пытаюсь объективно вникнуть в обсуждение...немогу... "укладывать", "раскладывать"...и применимо к ИТ эти слова вообще неуместны imho
11 Gary417
 
14.06.16
13:32
(10) +простите несдержался :)
12 FobusVGrunt
 
14.06.16
14:27
(10) метод УложитТЗ(загружает таблицу значений в базу данных, как таблицу базы данных), объекта SQLiteBase, не знаю этот метод укладывает ИТ, если укладывает, то можно проверить в ИТ добавить числовое целое значение   больше 2 147 483 647 или меньше (-2 147 483 648), а потом запросом, достать данные и посмотреть вернет обратно правильные значения. В ИТ, колонки по-моему без типов задаются, но думаю получится также как и с ТЗ. Пробовал просто INSERT добавлять, назад тоже не правильно выдает.
13 Ёпрст
 
14.06.16
14:29
Ну не делай уложить тз, делай тупо инсерт, делов-то
14 FobusVGrunt
 
14.06.16
14:31
(10) Если в самой таблице БД SQLite, явно не указан тип поля(колонки), то целые меньше -2 147 483 648 и больше 2 147 483 647, при выборке дадут неверный результат. Попробую просто выполнить запрос в 1С "SELECT -2147483648 as сумма" и посмотри что получится
15 FobusVGrunt
 
14.06.16
14:34
(13) Если в поле БД не указан явно тип, то и добавление INSERT не помогает. и инсертом одним запросом, можно добавить только одну строку для сборки sqllite по 1С, обсуждалась эта тема:
Как одним запросом вставить несколько строк в таблицу SQlite
а отдельно инсертом добавить даже 1000 строк, времени потянет просто космос
16 Djelf
 
14.06.16
14:45
(13) Медленно! Самое большое что грузил в sqlite это реестр лицензий, удалось выжать 3.5к записей в секунду, это пакетами по 10000 из тз, построчно даже обернув пакета в транзакцию получается медленнее раза в 2.
(15) А почему нельзя сразу в sqlite запихивать данные из запроса к 1С минуя тз?
17 FobusVGrunt
 
14.06.16
15:01
(16) С одной БД Выгружаю, в другую загружаю. Локальная БД SQLite в роли файла обмена с таблицами соответсвий по внутр ID объектов
18 FobusVGrunt
 
14.06.16
15:04
(16) Запросы идут к базе в :memory:, а потом укладываются с помощью ТЗ в локальную БД SQLite
19 FobusVGrunt
 
14.06.16
15:05
между :memory: и локальной можно замутить между собой запросы?
20 FobusVGrunt
 
14.06.16
15:08
(16) Я как то тестировал цикл построчно Insert с УложитьТЗ, там разница была в раз 100 быстрей по скорости по этому и поднял вопрос на форуме:
Как одним запросом вставить несколько строк в таблицу SQlite
21 Djelf
 
14.06.16
15:19
Можно вот так выкрутится

База.УложитьТЗ(тз,"таб1");
Запрос=База.НовыйЗапрос();
Запрос.ВыполнитьЗапрос("CREATE TABLE таб2 (кол1 REAL)");
Запрос.ВыполнитьЗапрос("INSERT INTO таб2 SELECT * FROM таб1");
Запрос.ВыполнитьЗапрос("SELECT * FROM таб2",тз);
22 FobusVGrunt
 
14.06.16
15:32
(21) не в моем случаи мне кажется, лучше при укладки тип задавать "Строка", меньше изменений делать. У меня такое применяется, когда нужно периодически добавлять в постоянную таблицу новые строки из другой ТЗ. Удобно когда в транзакции записываешь док или спр, во временную таблицу кидаешь соотвествия ID старой и в новой БД и если успешно завершилась транзакция, то копируются в основную.
23 Djelf
 
14.06.16
15:42
(19) Можно и не с одной файловой базой...

ATTACH DATABASE 'c:\temp1.db3' AS filebase1;
ATTACH DATABASE 'c:\temp2.db3' AS filebase2;
CREATE TABLE filebase1.t1 (val); -- file1
CREATE TABLE filebase2.t1 (val); -- file2
CREATE TABLE t1 (val); -- memory
INSERT INTO t1 (val) VALUES (1); -- memory
INSERT INTO filebase1.t1 (val) VALUES (2); -- file1
INSERT INTO filebase2.t1 (val) VALUES (3); -- file2
SELECT * from t1; -- (1)  -- memory
SELECT * from filebase1.t1; -- (2)  -- file1
SELECT * from filebase2.t1; -- (3)  -- file2
24 FobusVGrunt
 
14.06.16
15:46
(23) так тут две локальные БД, а запросы на выборку идут к БД в :memory:, а укладываются в локальноную (через ТЗ). Вторая 1С подключается к локальной и берет данные.
25 Djelf
 
14.06.16
15:52
(24) Ну а тз то зачем? Напрямую в файл из таблицы 1с или из таблицы в memory (main первая открытая база).
INSERT INTO file.table SELECT * FROM main.table
26 FobusVGrunt
 
14.06.16
15:56
(25) Не знал, что так можно. Надо будет попробовать.Спасибо за совет!
27 FobusVGrunt
 
14.06.16
15:59
Djelf а подключаемые виртуальные таблицы 1С,  у них поля указаны тип или как? не может такой ситуации возникнуть с целым числами -2 147 483 648 и > 2 147 483 647, как описано выше?
28 Djelf
 
14.06.16
16:12
(27) Ага, печаль... По быстрому установил тип курс валюты 19.0 и твой магический минус

SELECT Курс FROM Справочник_Валюты; -- хрень
SELECT Курс+0.0 FROM Справочник_Валюты; -- ок
SELECT cast(Курс as real) FROM Справочник_Валюты; -- ок
SELECT sum(Курс) FROM Справочник_Валюты where CODE='978' -- хрень
SELECT sum(Курс) FROM Справочник_Валюты -- ок
SELECT total(Курс) FROM Справочник_Валюты where CODE='978'

total тот же sum но резльтат гарантийно число
29 FobusVGrunt
 
14.06.16
16:25
(28) Да блин беда, тут дело не только в минусе, числа больше 2 147 483 647, тоже получается будет не правильно выдавать.... Если в реквизите указанна точность > 0, то не будет такой ситуации, даже если само число будет целое правильно?
30 Djelf
 
14.06.16
16:27
+(28) C 19.2 проблем нету, все ок.
31 FobusVGrunt
 
14.06.16
16:31
(30) Получается для постраховки, нужно через метаданные проверить точность для длинных чисел реквизита и если = 0, то нужно в запросе cast(Реквизит as real) или cast(Реквизит as DOUBLE).
Что кстати лучше real или double приводить к типу
32 FobusVGrunt
 
14.06.16
16:32
Вроде SQlite юзают не первых год, неужели ни у кого такой проблемы не возникло?
33 FobusVGrunt
 
14.06.16
17:30
Djelf, а чего если виртуальных таблицах 1С, точность > 0 спасает от этой ситуации, а в ТЗ (ТЗ.НоваяКолонка("Значение","Число",19,2)) не спасает?
34 Djelf
 
14.06.16
18:27
Не спасает потому что так уж там число хранится

тз.кол1 =  -2226062580.0000000;
Сообщить(тз.кол1);
-2226062580
35 FobusVGrunt
 
14.06.16
18:30
(34) А понятно
36 Djelf
 
17.06.16
22:23
1sqlite 1sqlite_3.8.11.1.bf7.zip
https://cloud.mail.ru/public/2m1f/4k42zyEjU

+ корректно выдает в 1с целые числа в диапазоне от -9223372036854775808 до 9223372036854775807
+ скорость не упала
- при выходе за диапазон sqlite все равно будет преобразовывать их в тип float, т.е. ~15 знаков в числе
37 FobusVGrunt
 
18.06.16
14:42
(36) О большое спасибо  Djelf!
38 FobusVGrunt
 
18.06.16
15:15
(36) Это относится только к подключаемым таблицам 1С?
Т.к. "SELECT -2147483648", все равно не работает
39 Djelf
 
18.06.16
15:43
(38) Должно работать. Ты точно новую 1sqlite загрузил?
SELECT sqlite_version() что выдает?
p.s. проверил выложенный файл - (38) все ок
40 FobusVGrunt
 
18.06.16
16:19
(39) 3.7.10
41 Djelf
 
18.06.16
16:20
(40) А должно быть 3.8.11.1 т.е. загружаешь старую.
42 FobusVGrunt
 
18.06.16
16:23
(41) Спасибо, ошибся ни туда кинул, все ОК, работает. Так это версия самой Sqlite или именно сборки под 1С
43 Djelf
 
18.06.16
16:40
(42) Это версия движка sqlite. Файл отличить можно по его свойствам "Версия продукта" - "1.0.2.6/3.8.11.1"
44 FobusVGrunt
 
18.06.16
16:58
(43) так может 3.8, уже и Insert поддерживает несколько в одном запросе?
45 Djelf
 
18.06.16
17:00
(44) Правильно думаешь. Изменений в движке со времен 3.7.10 огромное количество.
46 FobusVGrunt
 
18.06.16
17:03
(45) Отлично, спасибо!