Member 14114251 Ответов: 2

Подзапросы в этом контексте не допускаются. Допускаются только скалярные выражения


Привет

Может ли кто-нибудь помочь мне, пожалуйста, в моем приложении у меня есть метод ниже, чтобы обновить запись в базе данных, если она существует, а также вставить, если записи нет
public static int updateValue(int cellnum, int returnID, double? ценность)
{
int num = 0;

используя(sqlconnection для подключения = новое sqlconnection(clsGeneral.getConnectionString()))
{
использование(команда SqlCommand = соединение.CreateCommand())
{
строка str;

стр = "если не существует(выберите * от Валу, где ReturnID =" + returnID + " и CellID=(выберите CellID от [сотовый] где CellNum=" + cellnum + "))";

если (значение != 0.0)
{
сил += "вставить в Валу (CellID, ReturnID, Валу, TXT и FieldUsed, DteCreated, DteUpd) значения ((выберите CellID от[сотовый] где CellNum =" + cellnum + ")," + returnID + ", преобразовать(поплавок, заменить('" + значение + "',',','.')),",1,getdate(),то функцию getdate())";
str += " ELSE ";

str += строка.Функция concat(новый объект[] { "обновление [р] Набор [Р].[Значение]=заменить('", + стоимость , "',',','.'),[Валу].FieldUsed=1, где [Valu].ReturnID=", returnID " и [Valu].CellID=(выберите CellID из [Cell], где CellNum=", cellnum, ")" });

}
еще
{
сил += "вставить в Валу (CellID, ReturnID, Валу, TXT и FieldUsed, DteCreated, DteUpd) значения ((выберите CellID от[сотовый] где CellNum =" + cellnum + ")," + returnID + ", преобразовать(поплавок, заменить('" + значение + "',',','.')),",0,getdate(),то функцию getdate())";
str += " ELSE ";

str += строка.Функция concat(новый объект[] { "обновление [р] Набор [Р].[Значение]=конвертировать(поплавок, заменить('", +стоимость, "',',','.')),[Валу].FieldUsed=0, где [Valu].ReturnID=", returnID " и [Valu].CellID=(выберите CellID из [Cell], где CellNum=", cellnum, ")" });



}

команда.Свойство Commandtype = Значение Commandtype.Текст;
команда.Ул. свойства commandtext = ;
соединение.Открыть();
num = команда.Метод executenonquery();
}
}
возвратное число;
}
Я получаю нижеприведенную ошибку при сохранении, не могли бы вы помочь мне исправить ее горячим способом.

Подзапросы в этом контексте не допускаются. Допускаются только скалярные выражения

Что я уже пробовал:

public static int updateValue(int cellnum, int returnID, double? value)
{
    int num = 0;

    using(SqlConnection connection = new SqlConnection(clsGeneral.getConnectionString()))
    {
        using(SqlCommand command = connection.CreateCommand())
        {
            string str;

            str = "IF NOT EXISTS(SELECT * FROM Valu WHERE ReturnID = " + returnID + " AND CellID=(SELECT CellID FROM [Cell] WHERE CellNum=" + cellnum + "))";

            if (value != 0.0)
            {
                str += " INSERT INTO Valu (CellID, ReturnID, Valu, Txt, FieldUsed, DteCreated, DteUpd) VALUES ((SELECT CellID FROM[Cell] WHERE CellNum = " + cellnum + ")," + returnID + ", CONVERT(FLOAT, REPLACE('" + value + "',',','.')),'',1,getdate(),getdate())";
                str += " ELSE ";

                str += string.Concat(new object[] { "UPDATE [Valu] SET [Valu].[Valu]=REPLACE('", + value  , "',',','.'),[Valu].FieldUsed=1 WHERE [Valu].ReturnID=", returnID, " AND [Valu].CellID=(SELECT CellID FROM [Cell] WHERE CellNum=", cellnum, ")" });

            }
            else
            {
                str += " INSERT INTO Valu (CellID, ReturnID, Valu, Txt, FieldUsed, DteCreated, DteUpd) VALUES ((SELECT CellID FROM[Cell] WHERE CellNum = " + cellnum + ")," + returnID + ", CONVERT(FLOAT, REPLACE('" + value + "',',','.')),'',0,getdate(),getdate())";
                str += " ELSE ";

                str += string.Concat(new object[] { "UPDATE [Valu] SET [Valu].[Valu]=CONVERT(FLOAT, REPLACE('", +value, "',',','.')),[Valu].FieldUsed=0 WHERE [Valu].ReturnID=", returnID, " AND [Valu].CellID=(SELECT CellID FROM [Cell] WHERE CellNum=", cellnum, ")" });



            }

            command.CommandType = CommandType.Text;
            command.CommandText = str;
            connection.Open();
            num = command.ExecuteNonQuery();
        }
    }
    return num;
}

2 Ответов

Рейтинг:
7

MadMyche

Первое, что я заметил, это то, что этот код опасен! Добавление переменных в инструкцию SQL путем объединения строк-это приглашение к SQL-инъекции, которая является одной из 10 лучших уязвимостей всех времен.

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

Часть 1 этого решения состоит в том, чтобы превратить этот беспорядок в хранимая процедура Этот скрипт нужно будет запустить на SQL Server один раз, а затем мы можем вызвать его по имени в C# и просто передать значения

CREATE PROCEDURE dbo.Valu_CreateOrUpate (
   @ReturnID  INT, 
   @CellNum   INT, 
   @Value     FLOAT
) AS
BEGIN
   DECLARE @Now       DATETIME = GetDate()
   DECLARE @FieldUsed BIT = 0
   DECLARE @CellID    INT

   IF (@Value <> 0) SET @FieldUsed = 1

   SELECT @CellID = CellID FROM [Cell] WHERE CellNum = @CellNum

   IF NOT EXISTS(SELECT 1 FROM Valu WHERE ReturnID = @ReturnID AND CellID = @CellID)) BEGIN
      INSERT INTO Valu (CellID, ReturnID, Valu, Txt, FieldUsed, DteCreated, DteUpd)
      VALUES ( @CellID, @ReturnID, @Value, '', @FieldUsed, @Now, @Now)   
   END; ELSE BEGIN
      UPDATE [Valu]
      SET [Valu].[Valu] = @Value
      ,   [Valu].FieldUsed = @FieldUsed
      WHERE [Valu].ReturnID = @ReturnID
      AND [Valu].CellID = @CellID
   END
END
GO


Следующая часть-это гораздо более простой для чтения код C#, чтобы вызвать это. CommandText был изменен, чтобы быть именем процедуры, CommandType изменен, чтобы быть StoredProcedure, и переменные добавляются в команду через Parameters.AddWithValue() метод. Этот метод будет "автоматически вводить" значения в зависимости от того, с каким типом переменной вы работаете. Это вообще делает хорошую работу,
Однако; если одна из ваших переменных является нулевой он не будет включать его в запрос, если вы не передадите его явно как DBNull.Value Вам нужно будет решить, как обрабатывать значение nullable, которое есть в вашем коде .
public static int updateValue(int cellnum, int returnID, double? value) {
   int num = 0;

   using (SqlConnection connection = new SqlConnection(clsGeneral.getConnectionString())) {
      using (SqlCommand command = connection.CreateCommand()) {

         command.CommandText = "dbo.Valu_CreateOrUpate";
         command.CommandType = CommandType.StoredProcedure;

         command.Parameters.AddWithValue("@ReturnID", returnID);
         command.Parameters.AddWithValue("@CellNum", cellnum);
         command.Parameters.AddWithValue("@Value", value );     // ** watch for NULL **

         connection.Open();
         num = command.ExecuteNonQuery();
      }
   }
   return num;
}


Рейтинг:
0

ZurdoDev

Первый шаг-это переместить sql в хранимую процедуру и передать параметры. Весь этот встроенный sql трудно отлаживать и поддерживать, как вы можете видеть сейчас.

И вы должны изменить свою вставку на что-то вроде

INSERT INTO Value(CellID, ReturnID, Valu, Txt, FieldUsed, DteCreated, DteUpd)
SELECT CellID, @returnID, @value, '', 1, getDate(), getDate()
FROM [Cell]
WHERE CellNUm = @cellnum


У вас не может быть оператора SELECT, когда вы используете оператор VALUES. Поэтому просто используйте оператор SELECT сам по себе.


Member 14114251

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