Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как передать в хранимую процедуру массив (Excel VBA + ADO) / 17 сообщений из 17, страница 1 из 1
30.08.2018, 17:02
    #39695711
PATRI0T
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
Добрый день.
Вот, пытаюсь в своем проекте переписать код работы с базой, конкретно - запись через хранимые процедуры..
И возник вопрос, а как записывать массивы данных?
Конкретно у меня - автоматизация мебельного производства, запись заказов.
Есть шапка заказа, таблица с составом и таблица с производственными датами по участкам.
До этого я делал всё в цикле..

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
' Вставляем список дат
            CMD.CommandText = "Select * From ORDERS_DATE_PLAN;"
            .Open Source:=CMD
            ' В цикле записываем в базу таблицу
            For iRow = 1 To UBound(ArrDate)
                If ArrDate(iRow, 2) <> "" Then
                    .AddNew
                        !Order_ID = OrderID
                        !DATE_SECTOR = ArrDate(iRow, 1)
                        !DATE_DESCRIPTION = ArrDate(iRow, 2)
                        !PLAN_DATE = Replace(ArrDate(iRow, 3), ",", ".") ' исправление опечаток
                        !PLAN_DATE2 = Replace(ArrDate(iRow, 4), ",", ".") ' исправление опечаток
                    .Update
                End If
            Next iRow
            .Close



Но может есть способ организовать это через хранимую процедуру? чтобы цикл был уже в ней, и передавать ей несколько параметров, одним из которых будет массив данных.
Подскажите, можно ли такое реализовать?
...
Рейтинг: 0 / 0
30.08.2018, 17:25
    #39695735
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
PATRI0TПодскажите, можно ли такое реализовать?

Нельзя, запрещаю.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
30.08.2018, 17:36
    #39695746
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
PATRI0TПодскажите, можно ли такое реализовать?
Формируй строку через разделитель, в процедуре - разбивай её по этому разделителю.

Если таких "элементов массива" будет заведомо немного (не нарвёшься на ограничение макс. размера varchar) - то рабочий вариант.
...
Рейтинг: 0 / 0
30.08.2018, 18:20
    #39695774
PATRI0T
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
спасибочки )
...
Рейтинг: 0 / 0
30.08.2018, 19:54
    #39695809
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
а в ADO нельзя запускать Update-команду с параметрами?

что-то вроде такого ?
http://bobby-tables.com/adodotnet
...
Рейтинг: 0 / 0
30.08.2018, 20:00
    #39695815
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
Ariochа в ADO нельзя запускать Update-команду с параметрами?

Можно. Но аффтар не знает как.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
30.08.2018, 22:01
    #39695862
YuRock
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
Dimitry SibiryakovAriochа в ADO нельзя запускать Update-команду с параметрами?

Можно. Но аффтар не знает как.1000 "update-комманд" все равно наверняка будет хуже, чем один вызов "такой" процедуры.
...
Рейтинг: 0 / 0
31.08.2018, 12:12
    #39696132
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
YuRock,

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

даже при временном отключении индексов

или при начальном заполнении безиндексной GTT, а потом массовом переливе insert from select

зато нет проблем с типами данных, вплоть до SQL Injection
...
Рейтинг: 0 / 0
31.08.2018, 12:25
    #39696152
PATRI0T
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
хм.. так и что лучше? 1000 запросов на Update из клиентского приложения или хранимая процедура и передача данных через массив?

А еще посоветуйте что-нибудь годное почитать про это.. Статья\ресурс\книга.
Спасибо
...
Рейтинг: 0 / 0
31.08.2018, 12:45
    #39696181
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
PATRI0Tтак и что лучше? 1000 запросов на Update из клиентского приложения или хранимая процедура
и передача данных через массив?

На таких мелких объёмах - сугубо всё равно.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
31.08.2018, 12:53
    #39696190
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
Хорошие практически полезные книжки про ADO ?

не знаю где их искать, но явно не тут.

Возможно http://www.sql.ru/forum/visual-basic
...
Рейтинг: 0 / 0
31.08.2018, 12:56
    #39696194
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
PATRI0TНо может есть способ организовать это через хранимую процедуру?

зачем?

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

"использование SP" и "такой же, но с перламутровыми пуговицами", как вы понимаете, не может быть целью, если это не школьное задание.
аналогично "неиспользование SP" не может быть проблемой

значит и проблема и цель у вас какая-то другая, нам неизвестныe
...
Рейтинг: 0 / 0
31.08.2018, 15:45
    #39696307
PATRI0T
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
Ну у меня двоякая ситуация.
С одной стороны, у меня всё работало нормально через запросы из Excel и оно всё накрылось медным тазом после обновлении Win10 до 1803. Я по этому поводу создавал отдельную тему, помогли найти причину, и, как я понял, исправить ее без Микрософта не получится.. Поэтому нужно придумать другой способ общаться с базой. (Там была такая проблема, что нормально работал SELECT, INSERT, DELETE, но не работал UPDATE)

С другой стороны, я очень хотел бы разобраться, как вообще ПРАВИЛЬНО делаются клиент-серверные приложения, освоиться с работой с БД и вообще..

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

Поэтому и хотел разобраться
...
Рейтинг: 0 / 0
31.08.2018, 17:33
    #39696394
Arioch
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
я подозреваю, что для "правильного клиент-сервера" вообще Excel не подойдёт, хотя бы Access

Кроме ADO у Майкрософта есть ещё OLE DB
Например https://www.ibprovider.com/rus/documentation.html

Но вообще, вопрос как писать К/С на Бейсике лучше задавать в форуме про Бейсик.

А так - ну Грабера почитайте, он достаточно абстрактен (ен привязан к конкретным серверам-языкам-библиотекам) http://www.mysql.ru/docs/gruber/
...
Рейтинг: 0 / 0
10.09.2018, 16:36
    #39700514
PATRI0T
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
Спасибо всем за наводки
Получилась такая штука:
Хранимая процедура
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
/*
Процедура сохраняет производственные даты этапов по заказу
1. Проверить, есть ли заказ с таким ID.
2. Удалить все даты по заказу
3. Сохранить все даты заново
    Разобрать строку-массив
        Пока не встретим символ конца строки, берем значение полей, и пихаем их в переменные
        выполнить запрос на вставку данных
        Делать, Пока не закончатся строки

Пример входных данных
--ArrStr = 'Раскрой МДФ,Раскрой МДФ,1.08-2.08,,;Раскрой шпона ,Раскрой Шпона,1.08-2.08,,;Приклейка шпона +шлифовка,Приклейка шпона и шлифовка,3-6-7.08,,;Изготовление заготовки (Титова О.),Изг. Заготовки Титова,1-14.08,,;ЧПУ (Даник),not found,6.08-7.08,10.08-13.08,;ЦВЕТКОВ Н.   Сборка,Сборка,8-14.08,,;Склад (Люба),not found,15-16.08,,;Станок,Станок,15-16.08,,;ЯБЛОКОВА  Шлифовка,Шлифовка,17-22.08,,;Попов А.,Попов,1.08-8.08,,;Шлифовка (Попов),Шлифовка Попов,9.08-13.08,,;Л № 1  ЮЛЯ  Лакировка,Лакировка,23-30.08,,;ОКСАНА,Оксана,31.07,,;Упаковка,Упаковка,31.08,,;';
--OrderID=2636;
*/

create or alter procedure SAVE_ORDERS_DATES (
    ARRSTR varchar(30000),
    ORDERID integer,
    PlanDate_FirstStage varchar(20),
    PlanDate_Upack varchar(20)
    )
returns (
    ERRNUM smallint,
    ERRTEXT varchar(1000)
    )
as
    declare variable CURRSTR varchar(3000);
    declare variable ISDONE smallint = 0;
    declare variable sPos1 smallint;
    declare variable sPos2 smallint;
    declare variable OrderExist smallint;
    
    declare variable PDate1 VARCHAR(20);
    declare variable PDate2 VARCHAR(20);
    declare variable DSector VARCHAR(50);
    declare variable DDescr VARCHAR(50);

begin
 -- 1. Проверяем, есть ли такой заказ
    select ID from orders where id = :OrderID INTO :OrderExist;
    if (orderexist is null) then
        begin
            ERRNUM=1;
            ERRTEXT='Не найден заказ с ID ' || :OrderID;
            Suspend;
            Exit;
        End
 -- 2. Удаляем предыдущие данные
    Delete from orders_date_plan od where od.order_id = :OrderID;

 -- 3. В цикле расщепляем строку и добавляем данные
  While (IsDone=0) Do
    Begin
        sPos1 = POsition (';',arrstr);
        CURRSTR = SUBSTRING (arrstr FROM 1 FOR sPos1-1);
        -- Отрываем по одному значению и сохраняем в переменные
          -- DataDescription
            sPos2 = POsition (',',CURRSTR);
            DDescr= SUBSTRING(CURRSTR FROM 1 FOR sPos2-1);
            currstr = SUBSTRING (CurrSTr From sPos2+1 FOR CHAR_LENGTH(CurrStr));
          -- DateSector
            sPos2 = POsition (',',CURRSTR);
            DSector= SUBSTRING(CURRSTR FROM 1 FOR sPos2-1);
            currstr = SUBSTRING (CurrSTr From sPos2+1 FOR CHAR_LENGTH(CurrStr));
          -- Date1
            sPos2 = POsition (',',CURRSTR);
            PDate1= SUBSTRING(CURRSTR FROM 1 FOR sPos2-1);
            currstr = SUBSTRING (CurrSTr From sPos2+1 FOR CHAR_LENGTH(CurrStr));
        -- Date2
            sPos2 = POsition (',',CURRSTR);
            PDate2= SUBSTRING(CURRSTR FROM 1 FOR sPos2-1);
            currstr = SUBSTRING (CurrSTr From sPos2+1 FOR CHAR_LENGTH(CurrStr));
    -- Обновляем строку, отрезая разобранную часть
      arrstr = SUBSTRING (arrstr From sPos1+1 FOR CHAR_LENGTH(arrstr));

    -- 4. Вставляем данные
      Insert Into orders_date_plan  (order_id, date_sector, date_description, plan_date, plan_date2) VALUES (:orderid, :dsector, :ddescr,:pdate1, :pdate2);

    -- Проверка выхода
      if (:ArrStr = '') then
            IsDone=1;
    end
    -- 5. После всего обновляем ключевые даты в таблице заказов
  Update orders o set o.plan_date_firststage = :plandate_firststage, o.plan_date_pack = :plandate_upack where o.id= :orderid;

  errnum=0;
  errtext='ok';
  suspend;
  -- commit;
end


Функция упаковки массива в строку
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
Function ArrToString(Arr As Variant) As String
    Const DelimStr = ";"
    Const DelimColumn = ","
    
    Dim i As Integer, j As Integer
    Dim ResSTR As String
    
    ' В цикле проходим массив, и если значение не содержит в себе символов разделителей, то клеим его к результирующей строке
    For i = 1 To UBound(Arr)
        For j = 1 To UBound(Arr, 2)
            If InStr(Arr(i, j), DelimStr) > 0 Or InStr(Arr(i, j), DelimColumn) > 0 Then
                Call MsgBox("!Ошибка. Ячейка содержит символ разделитель. " & vbLf & " Индекс: " & i & ";" & j & vbLf & "Неправильные символы будут заменены на пробелы. Старайтесь их избегать", vbExclamation, "Неправильный символ")
                    Arr(i, j) = Replace(Arr(i, j), DelimStr, " ")
                    Arr(i, j) = Replace(Arr(i, j), DelimColumn, " ")
                    Arr(i, j) = Trim(Replace(Arr(i, j), "  ", " "))
            Else
                ResSTR = ResSTR & Arr(i, j) & DelimColumn
            End If
        Next j
        ResSTR = ResSTR & DelimStr ' В  конце клеем символ-разделитель конца строки
    Next i
    
    ArrToString = ResSTR
End Function



Основная процедура сохранения в базу
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
Sub S_СохранитьДаты(OrderID As Integer)
'...
' Опустил кусок кода, где объявляются переменные и формируется массив дат <===============
'...
' Формируем строку для передачи в ХП (Хранимую процедуру)
    ArrStr = ArrToString(ArrDate)
'=====
    Call CreateConnection
    If CN.State = adStateClosed Then Exit Sub
        CN.BeginTrans
        ' Формируем запрос
            With CMD
                .CommandType = adCmdStoredProc
                .CommandText = "SAVE_ORDERS_DATES"
                .NamedParameters = True
                .Parameters.Refresh ' Получили список параметров
                .Parameters(0).Value = ArrStr
                .Parameters(1).Value = OrderID
                .Parameters(2).Value = ДатаНачалаПроизводства
                .Parameters(3).Value = ДатаУпаковки
            End With
        ' Выполняем запрос.
            Set RS = CMD.Execute
            
        ' Если прошло без ошибок,
            If RS!ERRNUM = 0 Then
                CN.CommitTrans ' значит можно подтвердить транзакцию
            Else
                CN.RollbackTrans ' Или откатить
            End If
        
        Call TerminateConnection
End Sub



В принципе, мне понравилось работать с ХП..
Но пока побаиваюсь 2х вещей: сложность отладки и требовательность к более внимательному написанию кода (той части, которая выполняется на стороне Базы)
Потому как, если в хранимой процедуре что-то напутал - например, по глупости забыл в запросе UPDATE добавить критерий WHERE, то всё.. всем хана.. И самое главное, она все сделает молча. Вот ведь где ужас )
Когда весь код в одном месте, оно как-бы проще.. все перед глазами. А когда вот так, разделено на 2 части, то про особенности реализации давно написанной ХП легко забыть, что у тебя там и как..
И отладка сложна по отдельности.. сначала процедуру с тестовыми данными вылизываем через дебагер IBExpert-а, и потом, когда во всем уже уверены, пишем и отлаживаем код в VBA..
Короче тоже есть свои минусы.

==
В заключение, очень хотел бы попросить тех, у кого есть опыт и найдется время -- поглядеть на код и покритиковать...
...
Рейтинг: 0 / 0
10.09.2018, 16:43
    #39700519
Симонов Денис
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
PATRI0T,

хрень полнейшая. Зачем страдать онанизмом собирая и разбирая строку по разделителям, если можно сразу отправить нужные параметры на сервер.
...
Рейтинг: 0 / 0
10.09.2018, 16:51
    #39700522
PATRI0T
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как передать в хранимую процедуру массив (Excel VBA + ADO)
Раньше у меня так и было - правда не через ХП было организовано - макрос делал последовательные запросы к базе.
Но случилась проблема из за обновления Win10 и у меня перестал работать Update.. Поэтому пришлось делать всё через ХП

А там логика такая -
1. проверить, есть ли заказ с таким ID,
2. удалить все даты из таблицы дат по этому заказу
3. вставить массив дат
4. обновить инфу о ключевых датах в другой таблице..

У меня опыта мало, поэтому я придумал сделать так.. Да и сейчас я это не представляю, как сделать, если разбить на отдельные запросы.. Может потому, что я не умею пользоваться ХП...
Подскажите, как надо было?
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как передать в хранимую процедуру массив (Excel VBA + ADO) / 17 сообщений из 17, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]