Имя: Пароль:
1C
 
Заставить 1С каждый раз создавать новую временную таблицу в СУБД по одному набору колонок
,
0 TormozIT
 
гуру
22.05.23
08:50
Нужна идея. Как заставить 1С каждый раз создавать новую временную таблицу в СУБД по одному набору колонок даже в рамках одного соединения?
Пример
Первое выполнение

Выбрать 2 поместить аа

в СУБД делает

CREATE TABLE #tt4 (_Q_000_F_000 NUMERIC(1, 0))

А второе выполнение
Выбрать 2 поместить аа
в рамках того же соединения СУБД делает ничего (переиспользует #tt4). А надо чтобы опять выполнился запрос.
1 НафНаф
 
22.05.23
08:52
(0) удалять перед повторным использованием
2 TormozIT
 
гуру
22.05.23
08:54
(1) Удаление временной таблицы в СУБД не выполнится. Она останется.
3 НафНаф
 
22.05.23
08:59
(2) тогда огласите всю задачу

если я напишу "Выбрать 42 поместить аа" там же теперь 42?
4 TormozIT
 
гуру
22.05.23
09:01
(3) Речь не про строки таблицы, а про саму временную таблицу в СУБД. Ее содержимое конечно будет обновляться. Но сама она не удаляется, а переиспользуется. Это описано в документации.
5 trad
 
22.05.23
09:02
Выбрать 2 аа, 1 _guid
6 katamoto
 
22.05.23
09:04
(4) А зачем нужно, что бы именно удалялась?
7 Asmody
 
22.05.23
09:07
(0) сделай лишнюю колонку со случайным именем
8 TormozIT
 
гуру
22.05.23
09:15
(7) Не поможет. Играет роль только порядок и типы колонок.
9 TormozIT
 
гуру
22.05.23
09:16
Перефразирую (0) - хочу гарантировано увидеть в трассе СУБД запрос создания временной таблицы при выполнении своего запроса 1С
10 Chai Nic
 
22.05.23
09:21
(9) Временные таблицы удаляются при удалении менеджера временных таблиц. А его удаление зависит от области действия его переменной. То есть, нужно создавать запрос с явным или неявным МВТ в какой-то функции или процедуре.
11 TormozIT
 
гуру
22.05.23
09:24
(10) На уровне 1С да. Но на уровне СУБД не так. Там кэшируются (пустые) временные таблицы и потому после их удаления на уровне 1С - в СУБД они остаются но пустыми.
12 TormozIT
 
гуру
22.05.23
09:26
Пока единственный рабочий вариант - перебор длины фиктивной текстовой колонки.
Выбрать  2, ВЫРАЗИТЬ("" КАК СТРОКА(#123#)) поместить аа
На 100-й раз уже придется выполнить 100 лишних запросов.
13 Chai Nic
 
22.05.23
09:36
(11) То есть 1с не дает команду DROP TABLE для временных таблиц?
14 TormozIT
 
гуру
22.05.23
09:36
(13) УНИЧТОЖИТЬ (как и уничтожение менеджера временных таблиц) удаляет СТРОКИ таблицы в СУБД, а не саму таблицу. Т.е. выполняет TRUNCATE TABLE вместо DROP TABLE
15 Valdis2007
 
22.05.23
09:37
пишешь хранимую процедуру, которая дропает твою таблицу, запускаешь ее из 1с через скриптик
16 TormozIT
 
гуру
22.05.23
09:38
(15) Как удалить временную таблицу в чужом соединении СУБД? Вроде так нельзя.
17 Chai Nic
 
22.05.23
09:59
(14) А чем это поведение объясняется, интересно? Оптимизация? Так было всегда или с какого-то релиза платформы?
18 katamoto
 
22.05.23
10:04
(13) DROP TABLE на самом деле не удаляет временные таблицы в SQL Server, они всё равно кэшируются, чтоб не пересоздавать постоянно объекты.
19 TormozIT
 
гуру
22.05.23
10:05
(18) Ты уже про внутренний уровень СУБД. Он в рамках рассматриваемой задачи не интересен.
20 TormozIT
 
гуру
22.05.23
10:06
(17) Такое кэшироование временных таблиц в СУБД вроде бы с 8.3 началось. Сделано в частности для повышения вероятности переиспользования планов запросов.
21 katamoto
 
22.05.23
10:26
По идее, создание индекса на временной таблице должно приводить к построению новой таблицы, вместо использования закэшированной.
22 НафНаф
 
22.05.23
10:34
(8) ну значит последовательно увеличивай длину строкового поля (изменение типа) пока возможно, потом сбрасывай до 1 и т.д.
23 TormozIT
 
гуру
22.05.23
10:42
(21) Если индекс имеет ту же структуру, то он не пересоздается.
24 TormozIT
 
гуру
22.05.23
11:55
Попробую с другой стороны зайти к задаче. Есть ли простой способ в MSSQL программно создать скрипт создания временной таблицы на основе имеющейся временной таблицы?
25 JanK
 
22.05.23
12:52
26 Chai Nic
 
22.05.23
12:52
(24) ВЫБРАТЬ * ПОМЕСТИТЬ Новая_ВТ ИЗ Старая_ВТ
А "в MSSQL" это " уже про внутренний уровень СУБД. Он в рамках рассматриваемой задачи не интересен."
27 TormozIT
 
гуру
22.05.23
19:58
(25) Спасибо. После небольшого допила получился скрипт для создания скрипта создания временной таблицы на основе глобального имени существующей временной таблицы.
Проверено на MSSQL 2016

use tempdb;
DECLARE @table_name SYSNAME
DECLARE @table_nameLocal SYSNAME
SELECT @table_name = '%ГлобальноеИмяВременнойТаблицы%'
SELECT @table_nameLocal = '%ИмяНовойВременнойТаблицы%'

DECLARE
      @object_name SYSNAME
    , @object_id INT

SELECT
      @object_name = s.name
    , @object_id = s.[object_id]
from tempdb.sys.tables as s
WHERE s.name = @table_name

DECLARE @SQL NVARCHAR(MAX) = ''
;
SELECT @SQL ='CREATE TABLE ' + @table_nameLocal + CHAR(13) + '(' + CHAR(13) + STUFF((
    SELECT CHAR(9) + ', [' + c.name + '] ' +
        CASE WHEN c.is_computed = 1
            THEN 'AS ' + cc.[definition]
            ELSE UPPER(tp.name) +
                CASE WHEN tp.name IN ('varchar', 'char', 'varbinary', 'binary', 'text')
                       THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length AS VARCHAR(5)) END + ')'
                     WHEN tp.name IN ('nvarchar', 'nchar', 'ntext')
                       THEN '(' + CASE WHEN c.max_length = -1 THEN 'MAX' ELSE CAST(c.max_length / 2 AS VARCHAR(5)) END + ')'
                     WHEN tp.name IN ('datetime2', 'time2', 'datetimeoffset')
                       THEN '(' + CAST(c.scale AS VARCHAR(5)) + ')'
                     WHEN tp.name = 'decimal'
                       THEN '(' + CAST(c.[precision] AS VARCHAR(5)) + ',' + CAST(c.scale AS VARCHAR(5)) + ')'
                    ELSE ''
                END +
                CASE WHEN c.collation_name IS NOT NULL THEN ' COLLATE ' + c.collation_name ELSE '' END +
                CASE WHEN c.is_nullable = 1 THEN ' NULL' ELSE ' NOT NULL' END +
                CASE WHEN dc.[definition] IS NOT NULL THEN ' DEFAULT' + dc.[definition] ELSE '' END +
                CASE WHEN ic.is_identity = 1 THEN ' IDENTITY(' + CAST(ISNULL(ic.seed_value, '0') AS CHAR(1)) + ',' + CAST(ISNULL(ic.increment_value, '1') AS CHAR(1)) + ')' ELSE '' END
        END + CHAR(13)
    FROM sys.columns c WITH (NOWAIT)
    JOIN sys.types tp WITH (NOWAIT) ON c.user_type_id = tp.user_type_id
    LEFT JOIN sys.computed_columns cc WITH (NOWAIT) ON c.[object_id] = cc.[object_id] AND c.column_id = cc.column_id
    LEFT JOIN sys.default_constraints dc WITH (NOWAIT) ON c.default_object_id != 0 AND c.[object_id] = dc.parent_object_id AND c.column_id = dc.parent_column_id
    LEFT JOIN sys.identity_columns ic WITH (NOWAIT) ON c.is_identity = 1 AND c.[object_id] = ic.[object_id] AND c.column_id = ic.column_id
    WHERE c.[object_id] = @object_id
    ORDER BY c.column_id
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, CHAR(9) + ' ')
    + ')'  + CHAR(13)
PRINT @SQL
28 TormozIT
 
гуру
22.05.23
20:00
Ну а поиск глобального имени нужной временной таблицы делаю программно по точному совпадению набора колонок на базе такого запроса
    "SELECT
    |    c.name AS ИмяКолонки,
    |    c.column_id AS НомерКолонки,
    |    c.system_type_id AS НомерТипа,
    |    tb.name AS ИмяТаблицы
    |FROM
    |    tempdb.sys.columns AS c
    |    INNER JOIN tempdb.sys.tables AS tb
    |    ON tb.object_id = c.object_id
    |WHERE tb.name like '" + ИмяОригинальнойВТ + "_%'
    |ORDER BY НомерКолонки
    |";
29 Смотрящий
 
22.05.23
20:12
(0) Заставь ее использовать ##tt4 вместо #tt4. Насколько я помню ##tt4 как раз и будет "одноразовой" таблицей
30 JanK
 
23.05.23
09:17
(29) https://stackoverflow.com/questions/2920836/local-and-global-temporary-tables-in-sql-server

Но в общем даже без учёта неправильного синтаксиса - это совёт из разряда "станьте ёжиками".
Глупец, лишенный способности посмеяться над собой вместе с другими, не сможет долго выносить программирование. Фредерик Брукс-младший