Прочитать значение CSV в строку запроса SQL

Я пытаюсь взять значения (разделенные запятыми) из текстового поля и передать их в строку запроса в инструкции ExecuteSQL. Я не уверен, как это сделать правильно. Очевидная проблема заключается в том, что он сломается, если будет больше или меньше трех исключений. Мне нужно использовать массив или список, но я не знаю, как прочитать это обратно в строку запроса?

Это то, что у меня есть до сих пор:

Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
        Dim db As New Database
        If txtEmpExceptions.Text.ToString() IsNot Nothing Then
            Dim EmpExcept1 As String = txtEmpExceptions.Text.ToString().Split(",")(0)
            Dim EmpExcept2 As String = txtEmpExceptions.Text.ToString().Split(",")(1)
            Dim EmpExcept3 As String = txtEmpExceptions.Text.ToString().Split(",")(2)
            db.ExecuteSQL("Delete dbo.Employee where employeeID <> '" & EmpExcept1 & "' and employeeID <> '" & EmpExcept2 & "' and employeeID <> " & EmpExcept3, prodString)
        Else
            db.ExecuteSQL("Delete dbo.Employee", prodString)
        End If
    End Sub

person Kevin Schultz    schedule 09.07.2015    source источник
comment
Просто остановитесь на секунду и прочитайте этот Sql Объяснение инъекции   -  person Steve    schedule 10.07.2015
comment
@Steve - это небольшой исполняемый файл для рабочего стола, который используется несколькими сотрудниками для заполнения таблицы в БД. Но спасибо, SQL-инъекция вызывает большую озабоченность.   -  person Kevin Schultz    schedule 10.07.2015
comment
Большинство взломов внутри рабочих мест. Вам по-прежнему нужна защита от инъекций во внутренних системах, даже в настольных приложениях.   -  person Joel Coehoorn    schedule 10.07.2015
comment
Кроме того, разделение через запятую — это ужасный способ обработки данных CSV. В VB.Net взгляните на класс TextFieldParser.   -  person Joel Coehoorn    schedule 10.07.2015
comment
@JoelCoehoorn Я думаю, что это немного излишне для одной строки CSV.   -  person Crowcoder    schedule 10.07.2015
comment
@Crowcoder Только если вы можете доверять данным CSV. Если вы позволяете людям вводить произвольный текст, вам лучше использовать специальный синтаксический анализатор.   -  person Joel Coehoorn    schedule 10.07.2015
comment
Вы знаете, что CSV может содержать запятые в данных, верно? И что он может использовать символы, отличные от запятых, в качестве разделителей? И что их много, множество синтаксических анализаторов .NET CSV, которые могут правильно с этим справиться?   -  person Dour High Arch    schedule 10.07.2015
comment
ЕДИНСТВЕННЫЙ способ, которым это хотя бы отдаленно близко к безопасному, - это если вы единственный пользователь приложения ... и даже в этом случае это довольно плохая практика. Как уже говорили другие, попробуйте использовать что-то более чистое, чем это. Параметризируйте свои запросы и, ПОЖАЛУЙСТА, назовите свои кнопки иначе, чем по умолчанию. Также в вашем SQL отсутствует предложение from.   -  person user2366842    schedule 10.07.2015


Ответы (3)


Чтобы проверить, есть ли у вас все ваши входные данные, которые вы могли разделить раньше, а затем проверить количество элементов в массиве, созданном string.Split

Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
    Dim db As New Database
    Dim parts = txtEmpExceptions.Text.Split(",")
    If parts.Length <> 3 Then
       MessageBox.Show("Text must be splitted in 3 substrings")
       return
    End If
    Dim EmpExcept1 As String = parts(0)
    Dim EmpExcept2 As String = parts(1)
    Dim EmpExcept3 As String = parts(2)       
    ....

Обратите внимание, что TextBox.Text никогда не бывает Nothing. Вы можете удалить эту проверку.
(И не имеет прямого отношения к вашей проблеме, но, как я уже сказал в комментарии, вам действительно следует попытаться использовать другой подход к вашему запросу к базе данных, чтобы любой ценой избежать конкатенации строк)

person Steve    schedule 09.07.2015

Это должно обеспечить хороший баланс между вашим уровнем опыта и предотвращением SQL-инъекций:

Dim empIds As String = "bob, sally, fred" 'This would come from your textbox
Dim emps() As String = empIds.Split(",")

Dim qry As String = "DELETE FROM dbo.Employee WHERE "
Dim whereClause As String = " employeeID <> @param{0} AND "

For i As Integer = 0 To emps.Length - 1
    'Add "employeeID <> .. for as many ids as were parsed
    qry = String.Concat(qry, String.Format(whereClause, i))
    Dim paramName As String = String.Concat("@param", i)
    Dim par As new SqlParameter(paramName, SqlDbType.VarChar, 50) 'Assumes your employee ids are text type and max 50 length - adjust accordingly
    par.Value = emps(i)
    'Now add this parameter to your SqlCommand, I don't know how your db library does that

Next i

'Get rid of the last "AND"
qry = qry.Remove(qry.Length - 4)

'Now set the CommandText of  your SqlCommand to qry
'Then execute the command
person Crowcoder    schedule 09.07.2015

В sql можно создать табличный тип — вот пример из одной из моих баз. Измените по мере необходимости.

CREATE TYPE [dbo].[AddSample_Type] AS TABLE(
[JobID] [int] NOT NULL,
[SampleDescription] [nvarchar](1000) NOT NULL,
[Notes] [nvarchar](1000) NULL,
[SampleName] [nvarchar](200) NULL,
[StorageLocationID] [int] NULL,
[StorageDispositionID] [int] NULL,
[StorageNotes] [nvarchar](1000) NULL,
[EmployeeID] [int] NULL,
[CheckedOutToEmployee] [bit] NULL
)
GO

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

 CREATE PROCEDURE [dbo].[AddMultipleSamplesToJob]
@SamplesToAdd AddSample_Type Readonly
AS
BEGIN
select JobID,SampleDescription,Notes,SampleName,StorageLocationID,
StorageDispositionID,StorageNotes,EmployeeID,CheckedOutToEmployee, 0 as     SampleNumber
 from @SamplesToAdd
END

Теперь вы можете отправить таблицу, полную строк, в вашу хранимую процедуру из VB.

 Dim addSamplesTable As New EPI_JobBookDataSet.AddMultipleSamplesToJobDataTable
    Dim AddSamplesAdapter As New EPI_JobBookDataSetTableAdapters.AddMultipleSamplesToJobTableAdapter
'Datatable to be sent in the procedure
Dim TablesamplesToAdd As New EPI_JobBookDataSet.TableType_AddSampleTable
'Make a new row and load it with data
 Dim newSampleRow As EPI_JobBookDataSet.TableType_AddSampleRow =     TablesamplesToAdd.Rows.Add()
            newSampleRow.CheckedOutToEmployee = StorageActivityEntryTool1.WithEmployee
            newSampleRow.EmployeeID = StorageActivityEntryTool1.EmployeeID
            newSampleRow.JobID = JobID
            newSampleRow.Notes = r.Cells(ColumnNotes.Index).Value
            newSampleRow.SampleDescription = r.Cells(ColumnDescription.Index).Value
            newSampleRow.SampleName = r.Cells(ColumnSampleName.Index).Value
            newSampleRow.StorageDispositionID = StorageActivityEntryTool1.DispositionID
            newSampleRow.StorageLocationID = StorageActivityEntryTool1.LocationID
            newSampleRow.StorageNotes = "Some notes"
'Add more rows if desired
'
'Send the query
AddSamplesAdapter.Fill(addSamplesTable, TablesamplesToAdd)

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

person ThatGuy    schedule 10.07.2015
comment
Лично, когда я даю своим пользователям возможность вводить несколько строковых значений, им предоставляется представление сетки данных, которое помогает организовать информацию с их точки зрения. Затем я перемещаю данные в одну из этих таблиц типов, строку за строкой и передаю их в процедуру. - person ThatGuy; 10.07.2015