Цикл C # SQL в операторе вставки из строковых значений - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть оператор вставки, который создает новую строку в таблице:

string SQLQuery = "INSERT INTO TABLEABC VALUES('" + Rtext + "', '" + TDate + "')";

Но я хочу создать несколько строк для данных на 20 повторов с интервалами в 8 недель (56 дней).

Например:

Rtext TDate
John  23/11/2018

Я бы хотел, чтобы он создал:

Rtext TDate
John  23/11/2018
John  18/01/2019
John  15/03/2019
John  10/05/2019
John  05/07/2019
John  30/08/2019
John  25/10/2019
John  20/12/2019
John  14/02/2020
John  10/04/2020
John  05/06/2020
John  31/07/2020
John  25/09/2020
John  20/11/2020
John  15/01/2021
John  12/03/2021
John  07/05/2021
John  02/07/2021
John  27/08/2021
John  22/10/2021
John  17/12/2021

Ответы [ 4 ]

0 голосов
/ 23 ноября 2018

Я предпочел использовать параметры SQL и цикл for для выполнения команды вставки для каждой итерации, но вы должны очистить параметры перед началом следующего выполнения.Вот пример, предположив, что вы сначала конвертируете строку даты в DateTime:

string SQLQuery = "INSERT INTO TABLEABC (RText, TDate) VALUES (@RText, @TDate)";

// edit: TDate is a string, convert it to DateTime first
DateTime date;

if (DateTime.TryParseExact(TDate, "dd/MM/yyyy", CultureInfo.InvariantCulture, 
    DateTimeStyles.None, out date)
{
    using (var con = new SqlConnection(connectionString))
    {
        con.Open();
        using (var cmd = new SqlCommand(SQLQuery, con))
        {
            for (var i = 0; i < 20; i++)
            {
                cmd.Parameters.AddWithValue("@RText", Rtext);

                // add for next iterations
                if (i > 0)
                {
                    date = date.AddDays(56);
                }

                cmd.Parameters.AddWithValue("@TDate", date);

                cmd.ExecuteNonQuery();
                cmd.Parameters.Clear(); // clear existing parameters for next iteration
            }
        }
    }
}
else
{
    // handle invalid dates
}

Примечание: Если тип данных точно известен, используйте вместо него Parameters.Add()Parameters.AddWithValue().

0 голосов
/ 23 ноября 2018

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

, вам нужно использовать stringbuilder и добавлять строку вставки или конкатены в SQLQuery.Используйте код ниже.

Datetime myDate = Convert.toDatetime("23/11/2018")
string SQLQuery = "INSERT INTO TABLEABC VALUES('" + Rtext + "', '" + TDate + "');";
SQLQuery += "INSERT INTO TABLEABC VALUES('" + John  + "', '" + myDate + "');";

for (int i = 1; i <=19; i++)
{
      SQLQuery +=" INSERT INTO TABLEABC VALUES('" + John  + "', myDate.AddDays(56) );";
}
0 голосов
/ 23 ноября 2018

Во-первых, вы должны параметризовать свой запрос.Мой C # очень ржавый (плохой), поэтому вам придется извинить меня, если это не так, однако, если я вспомню (и мой Google-фу сработал), то вы захотите сделать что-то более похожее на:

string SQLQuery = "INSERT INTO TABLEABC VALUES(@RText, @TDate)";
SQLCommand Command = new SQLCommand(SQLQuery, YourConnection);
Command.Parameters.Add("@RText",SQLDbType.varchar);
Command.Parameters["@RText"].Value = RText; //Assumed variable name
Command.Parameters.Add("@TDate",SQLDbType.date); //Assumed datatype
Command.Parameters["@TDate"].Value = TDate; //Assumed variable name

Это не решает повторяющиеся пункты, поэтому первую строку можно заменить на:

string SQLQuery = "INSERT INTO TableABC SELECT @RText, DATEADD(WEEK, 8*I, @TDate) FROM (VALUES(0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19)) V(I);";

В качестве альтернативы вы можете использовать rCTE вместо виртуальной таблицы Tally.В SQL это будет выглядеть следующим образом:

WITH rCTE AS(
        SELECT @RText AS RText,
               @TDate AS TDate
               0 AS I
        UNION ALL
        SELECT RText,
               DATEADD(WEEK, (I+1)*8,TDate) AS TDate,
               I+1
        FROM rCTE
        WHERE I+1 <20
)
INSERT INTO TABLEABC
SELECT RText,
       TDate
FROM rCTE;

Если вы собираетесь использовать большое количество значений, масштабируемая таблица подсчета является подходящим способом:

WITH N AS(
        SELECT N
        FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS I
    FROM N N1 -10
         CROSS JOIN N N2 --100
         CROSS JOIN N N2 --1000
         CROSS JOIN N N2 --10000 --you get the idea
    )
INSERT INTO TABLEABC
SELECT TOP 500
       @RText,
       DATEADD(WEEK, (I-1)*8, @TDate)
FROM Tally;

rCTEв вышеприведенном смысле это метод RBAR, поэтому его скорость будет снижаться по мере увеличения числа строк.Таблица подсчета будет намного быстрее, не будет RBAR и не нуждается в опции MAXRECURSION.

0 голосов
/ 23 ноября 2018

Вы можете попробовать это.

DECLARE @i INT=0, @LastDate AS DATE=GETDATE()

WHILE (@i < 20)
BEGIN
    INSERT INTO TABLEABC VALUES('" + Rtext + "', '" + @LastDate + "')

    SET @LastDate = @LastDate.AddDays(56)
    SET @i=@i+1;
END
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...