【问题标题】:Incorrect syntax near 's'. Unclosed quotation mark after the character string ')''s' 附近的语法不正确。字符串 ')' 后的非闭合引号
【发布时间】:2023-03-25 05:26:01
【问题描述】:

我知道我应该为此使用参数化查询,但它是用于插入文本文件的内部工具。有人看到未封闭报价的错误吗?奇怪的是,我在 SQL Server 2014 中运行它,它在我删除“和 ; 在值分配的末尾后成功运行。但在我的项目中的 Visual Studio 中它需要”; 这是我的代码:

    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
            {
                string conn = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
                SqlConnection con = new SqlConnection(conn);
                string query = "Insert into BluStar(ProductID,Manufacturer,SKU,BlueStarSKU,MSRP,RoughSummary,COST,Inventory,Weight,CAT4th,CAT1st,CAT2nd,CAT3rd,ProductName,Genre,ProductName2,RougherSummary,Cat_4th,Field1,Field2,Field3,Field4,Field5,Field6,Field7,Field8,Field9,Field10,Field11,Field12,Field13) Values('" + ds.Tables[0].Rows[i][0].ToString() + "','" + ds.Tables[0].Rows[i][1].ToString() + "','" + ds.Tables[0].Rows[i][2].ToString() + "','" + ds.Tables[0].Rows[i][3].ToString() + "','" + ds.Tables[0].Rows[i][4].ToString() + "','" + ds.Tables[0].Rows[i][5].ToString() + "','" + ds.Tables[0].Rows[i][6].ToString() + "','" + ds.Tables[0].Rows[i][7].ToString() + "','" + ds.Tables[0].Rows[i][8].ToString() + "','" + ds.Tables[0].Rows[i][9].ToString() + "','" + ds.Tables[0].Rows[i][10].ToString() + "','" + ds.Tables[0].Rows[i][11].ToString() + "','" + ds.Tables[0].Rows[i][12].ToString() + "','" + ds.Tables[0].Rows[i][13].ToString() + "','" + ds.Tables[0].Rows[i][14].ToString() + "','" + ds.Tables[0].Rows[i][15].ToString() +
                "','" + ds.Tables[0].Rows[i][16].ToString() + "','" + ds.Tables[0].Rows[i][17].ToString() + "','" + ds.Tables[0].Rows[i][18].ToString() + "','" + ds.Tables[0].Rows[i][19].ToString() + "','" + ds.Tables[0].Rows[i][20].ToString() + "','" + ds.Tables[0].Rows[i][21].ToString() + "','" + ds.Tables[0].Rows[i][22].ToString() + "','" + ds.Tables[0].Rows[i][23].ToString() + "','" + ds.Tables[0].Rows[i][24].ToString() + "','" + ds.Tables[0].Rows[i][25].ToString() + "','" + ds.Tables[0].Rows[i][26].ToString() + "','" + ds.Tables[0].Rows[i][27].ToString() + "','" + ds.Tables[0].Rows[i][28].ToString() + "','" + ds.Tables[0].Rows[i][29].ToString() + "','" + ds.Tables[0].Rows[i][30].ToString() + "')";
                con.Open();
                SqlCommand cmd = new SqlCommand(query, con);
                cmd.ExecuteNonQuery();
                con.Close();
            }

这是我必须从控制台转换为 MVC 以读取 csv 文件的代码。

    <%@ Page Language="C#" %>
<html>
<head>
   <title>read file insert into data base</title>
</head>
<body>
<%@Import namespace=System.Data %>
<%@Import namespace=System.Data.SqlClient %>
<% 

System.IO.StreamReader sr = new System.IO.StreamReader("/testdata/test.csv");
string line;
while(sr.Peek() != -1)
{
   line = sr.ReadLine();
   String[] parts = line.Split('\t');
   Response.Write(Server.HtmlEncode(parts[3]) + "<br/>");

string conn = "";
string Manu;
string sku;
Decimal msrp = Convert.ToDecimal(parts[4]);  
conn = ConfigurationManager.ConnectionStrings["Conn"].ToString(); 
SqlConnection objsqlconn = new SqlConnection(conn); 
objsqlconn.Open(); 
SqlCommand objcmd = new SqlCommand("Insert into ScanSource(Manufacture,SKU,MSRP) Values(@Manu, @sku,@msrp)", objsqlconn);
objcmd.Parameters.AddWithValue("@Manu",parts[1]);
objcmd.Parameters.AddWithValue("@sku",parts[3]);
objcmd.Parameters.AddWithValue("@msrp",msrp);
objcmd.ExecuteNonQuery(); 
}
%>
</body>
</html>

【问题讨论】:

  • 使用调试器查看query 填充后的内容。如果需要,将 SQL 复制到 SSMS 并在那里运行。然后,阅读 SQL 注入攻击。
  • 字符串中有撇号吗?
  • “内部”或不参数化您的查询是要走的路。此外,在编写查询时,不要害怕在每列之后添加空格(甚至是新行)。能够阅读这一点至关重要。如果我要调试它,我要做的第一件事就是格式化代码,使其清晰易读。然后我很可能会将其移动到存储过程中,添加一些验证、错误处理并正确处理我的连接对象。
  • 您容易受到sql injection attacks 的攻击。修复它,你的语法错误就会消失。
  • 找不到撇号。 @鬼。在 Sql 中运行它并且运行良好,但在查询末尾没有“;”。Visual Studio 不喜欢没有“;在末尾。我知道 sql 注入,但它是一种内部工具,不适用于实时生产。

标签: sql-server asp.net-mvc-5


【解决方案1】:

您的桌子也需要一些认真的帮助。你有像Field1,Field2这样的东西......这太糟糕了。考虑当您需要添加 Field14 时会发生什么。您将不得不在任何地方更新所有内容。这种东西属于子表。

我不会在这里发布完整的解决方案,因为有很多列,我不知道什么是数据类型。

这应该让你开始。

Insert into BluStar
(
    ProductID
    , Manufacturer
    , SKU
    , BlueStarSKU
    , MSRP
    , RoughSummary
    , COST
    , Inventory
    , Weight
    , CAT4th
    , CAT1st
    , CAT2nd
    , CAT3rd
    , ProductName
    , Genre
    , ProductName2
    , RougherSummary
    , Cat_4th
    , Field1
    , Field2
    , Field3
    , Field4
    , Field5
    , Field6
    , Field7
    , Field8
    , Field9
    , Field10
    , Field11
    , Field12
    , Field13
) 
Values
(
    @ProductID
    , @Manufacturer
    , @SKU
    , @BlueStarSKU
    , @MSRP
    , @RoughSummary
    , @COST
    , @Inventory
    , @Weight
    , @CAT4th
    , @CAT1st
    , @CAT2nd
    , @CAT3rd
    , @ProductName
    , @Genre
    , @ProductName2
    , @RougherSummary
    , @Cat_4th
    , @Field1
    , @Field2
    , @Field3
    , @Field4
    , @Field5
    , @Field6
    , @Field7
    , @Field8
    , @Field9
    , @Field10
    , @Field11
    , @Field12
    , @Field13
)

cmd.Parameters.Add("@ProductID", SqlDbType.Int).Value = int.parse(ds.Tables[0].Rows[i][0].ToString());

【讨论】:

  • 我知道。该项目每周发送 2 个文件。我的任务是制作一个工具来插入文件,无论是制表符还是管道分隔。糟透了。我真的很感激帮助。 @肖恩兰格
  • 这些字段标题对于数据人员每周收到的每个文件都是相同的。不会添加其他字段。
  • 如果格式一致,那么我仍然建议对过程使用表值参数,而不是逐行遍历数据集。您使用列创建用户定义的表类型。然后创建一个将其作为参数接收的过程。从 dotnet 方面,您只需传递您的数据表。没有比这更简单的了。
  • 谢谢@Sean Lange 我是这方面的新手。一天比一天好。目前找不到任何关于数据库访问、使用 MVC 的 Sql Server 的好书。只是必须操纵的教程。没有真正的组件结构分解以有效地将数据读入表格,因此我可以制作自己的自定义代码。尤其是 csv。
【解决方案2】:

这是另一种使用表值参数的替代方法。现在您必须意识到我无法对此进行测试,因此可能需要进行一些调整。另外我不知道您的表中有哪些数据类型,因此您需要调整这些数据类型。

在您可以使用表值参数之前,您必须创建类型。以下是您可以采取的方法。

CREATE TYPE BluStar AS TABLE
(
    ProductID int
    , Manufacturer varchar(10)
    , SKU varchar(10)
    , BlueStarSKU varchar(10)
    , MSRP varchar(10)
    , RoughSummary varchar(10)
    , COST varchar(10)
    , Inventory varchar(10)
    , Weight varchar(10)
    , CAT4th varchar(10)
    , CAT1st varchar(10)
    , CAT2nd varchar(10)
    , CAT3rd varchar(10)
    , ProductName varchar(10)
    , Genre varchar(10)
    , ProductName2 varchar(10)
    , RougherSummary varchar(10)
    , Cat_4th varchar(10)
    , Field1 varchar(10)
    , Field2 varchar(10)
    , Field3 varchar(10)
    , Field4 varchar(10)
    , Field5 varchar(10)
    , Field6 varchar(10)
    , Field7 varchar(10)
    , Field8 varchar(10)
    , Field9 varchar(10)
    , Field10 varchar(10)
    , Field11 varchar(10)
    , Field12 varchar(10)
    , Field13 varchar(10)
)

现在我们在 sql server 中拥有了自己的数据类型,可以模仿我们实际表的样子。这可能看起来有点矫枉过正,但请记住,我们将传入一整组行,而不是为每一行单独插入。这是我们的程序的样子。

create procedure BluStar_Insert
(
    @BluStar BluStar READONLY
) as

    Insert into BluStar
    (
        ProductID
        , Manufacturer
        , SKU
        , BlueStarSKU
        , MSRP
        , RoughSummary
        , COST
        , Inventory
        , Weight
        , CAT4th
        , CAT1st
        , CAT2nd
        , CAT3rd
        , ProductName
        , Genre
        , ProductName2
        , RougherSummary
        , Cat_4th
        , Field1
        , Field2
        , Field3
        , Field4
        , Field5
        , Field6
        , Field7
        , Field8
        , Field9
        , Field10
        , Field11
        , Field12
        , Field13
    ) 
    select 
        ProductID
        , Manufacturer
        , SKU
        , BlueStarSKU
        , MSRP
        , RoughSummary
        , COST
        , Inventory
        , Weight
        , CAT4th
        , CAT1st
        , CAT2nd
        , CAT3rd
        , ProductName
        , Genre
        , ProductName2
        , RougherSummary
        , Cat_4th
        , Field1
        , Field2
        , Field3
        , Field4
        , Field5
        , Field6
        , Field7
        , Field8
        , Field9
        , Field10
        , Field11
        , Field12
        , Field13
    from @BluStar

这一切都很好,但如果没有来自 dotnet 的示例,它并没有多大帮助。这旨在成为整个 dotnet 代码。没有更多的循环。

using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString))
{
    conn.Open();
    using (SqlCommand cmd = SqlCommand("BluStar_Insert", conn))
    {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@BluStar", ds.Tables[0]));
        cmd.ExecuteNonQuery();
    }
}

【讨论】:

  • 哇,太棒了。谢谢@Sean Lange
  • 我刚刚添加了我试图从 aspx 更改为 MVC 以插入 csv 文件的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-20
  • 2011-02-10
  • 1970-01-01
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多