2015-12-01 5 views
1

У меня было это работать несколько недель назад, но теперь я не уверен, что я сделал, что заставило его больше не работать. Я даже не получаю сообщение об ошибке, чтобы выяснить, что может быть неправильным. Когда я нажимаю кнопку, которую я сделал, чтобы вставить строку в таблицу, ничего не происходит. Форма очищается, и таблица запрашивается, но часть INSERT кода ничего не делает.VBA: Почему мой код INSERT не работает?

Public Sub Command125_Click() 
    'Add row for downtime 

    Dim dbsCurrent As Database 
    Set dbsCurrent = CurrentDb 

    dbsCurrent.Execute " INSERT INTO tbl_Downtime " _ 
    & "(job, suffix, production_date, reason, downtime_minutes, comment, shift) VALUES " _ 
    & "('" & Me.Text116 & "','" & Me.Text118 & "','" & Me.Text126 & "','" & Me.Text121 & "','" & Me.Text123 & "','" & Me.Text128 & "','" & Me.Text144 & "');" 

    Call ClearControl(Me.Text116) 
    Call ClearControl(Me.Text118) 
    Call ClearControl(Me.Text126) 
    Call ClearControl(Me.Text121) 
    Call ClearControl(Me.Text123) 
    Call ClearControl(Me.Text128) 
    Call ClearControl(Me.Text144) 

    Me.subrpt_DowntimeTable.Requery 

End Sub 

код Пытаюсь на основе @ ответ Hambone в:

Public Sub Command125_Click() 

Dim dbsCurrent As Database 
Set dbsCurrent = CurrentDb 

Dim query As QueryDef 
    Dim sql As String 

    For Each query In CurrentDb.QueryDefs 
     If query.Name = "InsertDowntime" Then 
     Exit For 
     End If 
    Next query 

    If query Is Nothing Then 
     sql = "parameters " & _ 
     "P1 text, P2 text, P3 Date, P4 Text, P5 Number, P6 Text, P7 Text;" & _ 
     "insert into [tbl_Downtime] " & _ 
     "(job, suffix, production_date, reason, downtime_minutes, comment, shift) " & _ 
     " VALUES ([P1], [P2], [P3], [P4], [P5], [P6], [P7])" 

     Set query = CurrentDb.CreateQueryDef("InsertDowntime", sql) 
    End If 

    query.Parameters("P1").Value = "test1" 
    query.Parameters("P2").Value = "test2" 
    query.Parameters("P3").Value = Now() 
    query.Parameters("P4").Value = "test3" 
    query.Parameters("P5").Value = 15 
    query.Parameters("P6").Value = "Miles O'Brien is a darn good transporter chief" 
    query.Parameters("P7").Value = "test6" 

    query.Execute 

    MsgBox query.Parameters("P1").Value & query.Parameters("P2").Value & query.Parameters("P3").Value & query.Parameters("P4").Value & query.Parameters("P5").Value & query.Parameters("P6").Value & query.Parameters("P7").Value 

    Me.subrpt_DowntimeTable.Requery 

End Sub 
+2

Вы уязвимы для [SQL-инъекций] (http://bobby-tables.com) –

+0

@MarcB Это форма, которая будет использоваться только в сети компании. Я не беспокоюсь о SQL-инъекции. – whatwhatwhat

+2

удачи в этом отношении, когда кто-то комментирует комментарий «Майлз О'Брайен - штопающий хороший начальник транспортера». просто потому, что полезная нагрузка не является «вредоносной», не означает, что у вас НЕ возникнет проблема. –

ответ

1

MarkB и gmiley абсолютно правы в использовании параметров. Это немного больше кода спереди и бесчисленное количество часов, сохраненных позже. И это хорошая практика.

Это говорит о том, что для собственного запроса на доступ (а не для запроса базы данных ADO) это не самый простой процесс в мире. Нормальный материал ADO, на мой взгляд, начинает иметь смысл после того, как вы сделаете это время или два, но для запроса Access мне все равно придется возвращаться и плагиатировать старые примеры, чтобы заставить его работать.

В вашем случае, я думаю, что что-то подобное будет делать трюк:

Dim query As QueryDef 
    Dim sql As String 

    For Each query In CurrentDb.QueryDefs 
    If query.Name = "InsertDowntime" Then 
     Exit For 
    End If 
    Next query 

    If query Is Nothing Then 
    sql = "parameters " & _ 
     "P1 text, P2 text, P3 Date, P4 Text, P5 Number, P6 Text, P7 Text;" & _ 
     "insert into [tbl_Downtime] " & _ 
     "(job, suffix, production_date, reason, downtime_minutes, comment, shift) " & _ 
     " VALUES ([P1], [P2], [P3], [P4], [P5], [P6], [P7])" 

    Set query = CurrentDb.CreateQueryDef("InsertDowntime", sql) 
    End If 

    query.Parameters("P1").Value = "test1" 
    query.Parameters("P2").Value = "test2" 
    query.Parameters("P3").Value = Now() 
    query.Parameters("P4").Value = "test3" 
    query.Parameters("P5").Value = 15 
    query.Parameters("P6").Value = "Miles O'Brien is a darn good transporter chief" 
    query.Parameters("P7").Value = "test6" 

    query.Execute 

Вы тянули свои данные из текстовых коробок. Я использовал жестко заданные значения, чтобы продемонстрировать, что это также управляет вводом данных, если ваши значения не являются всем текстом. Нет необходимости указывать «текст» или «# хэш-даты». Вы можете, очевидно, изменить их обратно на Me.TextBox123 и изменить типы данных в соответствии с вашими фактическими полями в tbl_Downtime.

- редактировать 12/3/15 -

Весь раздел кода из For Each query In CurrentDb.QueryDefs всего пути до query.Parameters мог теоретически быть опущены, если у вас уже есть запрос с этим текстом запроса в ней (как в вы вошли в Access, создал запрос, пошел с точки зрения дизайна для зрения SQL и напечатал это в и назвали его InsertDowntime):

parameters 
P1 text, P2 text, P3 Date, P4 Text, P5 Number, P6 Text, P7 Text; 
insert into [tbl_Downtime] 
(job, suffix, production_date, reason, downtime_minutes, comment, shift) 
VALUES ([P1], [P2], [P3], [P4], [P5], [P6], [P7]) 

Потому что вы этого не сделаете, я только что создал, что с помощью кода. Если вы попытаетесь создать его снова, Access будет блевать, потому что InsertDowntime уже существует.

В любом случае, как только она существует, то, как вы можете управлять это, говоря

Dim query As QueryDef 
Set query = CurrentDb.QueryDefs("InsertDowntime") 

А потом все остальное должно быть, как я есть.

Лично я бы выбрал вариант 2 - создайте запрос в Access и сохраните его как постоянный объект и получите доступ к нему так, как я только что перечислил выше. Полагаю, я мог бы это сказать, но ваш вопрос был VBA-иш, и я сохранил его VBA-plus, я думал, что способность создавать запрос динамически - это классно.

+0

Я не понимаю, что 'Для каждого запроса In .... Следующий запрос' часть для ... – whatwhatwhat

+0

Это проверяет, был ли запрос уже создан, и если да, используйте его вместо создания нового. Накладные расходы (хотя и минимальные) связаны с созданием queryDef, поэтому, не создавая его снова и снова, мы можем создать его один раз и использовать его для нескольких вставок. Кроме того, вы можете создать этот запрос через конструктор и просто использовать его 'query = CurrentDb.QueryDefs (« InsertDowntime »)', но это зависит от вас. Мне интересно, если вы попробуете это и как это работает. – Hambone

+0

К сожалению, он не работает :(Я отредактировал свой вопрос, чтобы показать код, который я использую. – whatwhatwhat

0

Согласно нашей дискуссии, вы хотели бы посмотреть в параметризованных запросов: https://support.microsoft.com/en-us/kb/181734

Основными причинами этого являются: 1) он обеспечит безопасность вашего кода от преднамеренной или непреднамеренной инъекции SQL. Поскольку пользовательский ввод не всегда может контролироваться в свободных формах, гарантируя, что ваш запрос параметризован, невозможно выполнить произвольный код; и 2) Считываемость, это делает намного легче читать код, когда значения параметризуются.

1

Я бы не построил SQL-Statement в Execute-Method. Создайте переменную и сначала создайте строку. Таким образом, вы можете отлаживать фактическое значение и тестировать его отдельно.

Вы также можете попробовать опцию dbFailOnError для Execute-Method.

Dim stmt as String 
stmt = "INSERT INTO....." 
dbsCurrent.Execute stmt, dbFailOnError 

Протестируйте инструкцию INSERT с различными входами. Не важно, что обычный пользователь будет вводить в форму, но то, что ему разрешено делать приложением. Если вход не проверен, и пользователь может ввести все, что захочет, то запрос может выйти из строя, произвести странные результаты или - как указано - позволяет SQL-инъекцию. Лучшая инъекция SQL - та, которую вы, как разработчик, никогда не заметите. Значит, ты не знаешь, что у тебя проблемы.

Смежные вопросы