0

我一直在写这个查询。我有这些表:

美食:美食
ID
美食名称美食
类型

菜肴:
DishID
DishName
CuisineID

设施:
FacilityID
FacilityName

RestaurantDish: RestaurantDishID RestaurantID DishID

餐厅: RestaurantID Name City Location PhoneNo

我必须根据用户选择的设施或菜肴或菜肴来显示餐厅。一旦我有一个餐厅列表,我必须通过每个用户选择进一步细化相同的列表。我写了这个不起作用的程序:

          ALTER PROCEDURE [dbo].[spGetFilterData]
@searchText NVARCHAR(MAX),
@DishIDs NVARCHAR(200) ,
@FacilitDs NVARCHAR(200) ,
@CuisineIDs NVARCHAR(200)
 AS 
BEGIN

    SET NOCOUNT ON;

    DECLARE @sql NVARCHAR(MAX)
    SET @sql = '';

    SET @sql = 'SELECT  RestaurantID ,
            Name ,
            City ,
            Location ,
            Country ,
            PhoneNo1 ,
            PhoneNo2 ,
            PhoneNo3 ,
            FaxNumber ,
            Timings ,
            HappyHour ,
            Menu ,
            Buffet ,
            Rating ,
            DateCreated ,
            Datemodified ,
            DateDeleted
    FROM    dbo.Restaurants AS r
    WHERE   ( RestaurantID IN (
              SELECT    rd.RestaurantID
              FROM      dbo.RestaurantDish AS rd
                        INNER JOIN dbo.Dishes1 AS d ON d.DishID = rd.DishID
              WHERE     ( d.DishName LIKE ''%' + @searchText + '%'''

    IF @DishIDs <> '' 
        BEGIN
            SET @sql =@sql + '   AND d.DishID IN ( ' + @DishIDs + ' )'

        END 
    SET @sql =@sql + ') ) )'       
    SET @sql =@sql + ' AND ( RestaurantID IN (
                 SELECT rf.RestaurantID
                 FROM   dbo.RestaurantFacility AS rf
                        INNER JOIN dbo.Facilities1 AS f ON f.FacilityID = rf.FacilityID
                 WHERE  ( f.FacilityName LIKE ''%' + @searchText + '%'''
    IF @FacilitDs <> '' 
        BEGIN
            SET @sql =@sql + ' AND f.FacilityID IN ( ' + @FacilitDs + ' )'
        END
    SET @sql =@sql + ') ) )'  
    SET @sql =@sql + '  OR ( RestaurantID IN (
                 SELECT RestaurantID
                 FROM   dbo.RestaurantDish
                 WHERE  ( DishID IN (
                          SELECT    dbo.RestaurantDish.DishID
                          FROM      dbo.Cuisine1
                          WHERE     ( CuisineName LIKE ''%' + @searchText
        + '%'')'
    IF @CuisineIDs <> '' 
        BEGIN
            SET @sql = @sql +' AND CuisineID IN ( ' + @CuisineIDs + ' )'
        END
    SET @sql =@sql + ') ) ))'                         
    SET @sql =@sql + '  OR ( Name LIKE ''%' + @searchText + '%'')
            OR ( City LIKE ''%' + @searchText + '%'')
            OR ( Country LIKE ''%' + @searchText + '%'')
            OR ( Buffet LIKE ''%' + @searchText + '%'')
            OR ( Location LIKE ''%' + @searchText + '%'')'
    EXECUTE sp_executesql @sql;     
END

我不知道还能做什么..这是我的课:

         public class DBAccess
       {
        public DBAccess()
       {
    //
    // TODO: Add constructor logic here
    //
        }
private SqlConnection GetConnection()
{
    SqlConnection con = null;
    try
    {
        string strCon = ConfigurationManager.ConnectionStrings["food4uConnectionString"].ConnectionString;
        con = new SqlConnection(strCon);
        con.Open();

    }
    catch (Exception ex)
    {
        con.Close();
        throw;
    }
    return con;
}

public List<Restaurants> GetAllRestaurents(string searchText, string dishIDs, string facilityIDs, string cuisineIDS)
{
    List<Restaurants> restaurants = null;
    try
    {
        SqlCommand cmd = new SqlCommand("spGetFilterData", GetConnection());
        cmd.CommandType = System.Data.CommandType.StoredProcedure;

        cmd.Parameters.AddWithValue("searchText", searchText);
        cmd.Parameters.AddWithValue("DishIDs", dishIDs);
        cmd.Parameters.AddWithValue("FacilitDs", facilityIDs);
        cmd.Parameters.AddWithValue("CuisineIDs", cuisineIDS);

        SqlDataReader dreader = cmd.ExecuteReader();
        restaurants = new List<Restaurants>();
        while (dreader.Read())
        {
            restaurants.Add(new Restaurants()
            {
                RestaurantID = (int)dreader["RestaurantID"],
                Name = (string)dreader["Name"],
                City = (string)dreader["City"],
                Country = (string)dreader["Country"],
                Location = (string)dreader["Location"],
                PhoneNo1 = (string)dreader["PhoneNo1"],
                PhoneNo2 = (string)dreader["PhoneNo2"],
                PhoneNo3 = (string)dreader["PhoneNo3"],
                Menu = (string)dreader["Menu"],
                HappyHour = (string)dreader["HappyHour"],
                Buffet = (string)dreader["Buffet"],
                Rating = (string)dreader["Rating"],
                FaxNo = (string)dreader["FaxNumber"],
                Timings = (DateTime)dreader["Timings"],
                DateCreated = (DateTime)dreader["DateCreated"],
                DateDeleted = (DateTime)dreader["DateDeleted"],
                Datemodified = (DateTime)dreader["DateModified"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return restaurants;
}

public List<Facilities1> GetFacilities(int restaurentID, string facilityID)
{
    List<Facilities1> facilities = null;
    try
    {
        SqlCommand cmd = new SqlCommand("spGetFacilities", GetConnection());
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("RestaurantID", restaurentID);
        cmd.Parameters.AddWithValue("FacilityID", facilityID);
        SqlDataReader dreader = cmd.ExecuteReader();
        facilities = new List<Facilities1>();
        while (dreader.Read())
        {
            facilities.Add(new Facilities1()
            {
                FacilityID = (int)dreader["FacilityID"],
                FacilityName = (string)dreader["FacilityName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return facilities;
}

public List<Dishes1> GetDishes(int restaurentID, string dishID)
{
    List<Dishes1> dishes = null;
    try
    {
        SqlCommand cmd = new SqlCommand("spGetDishes", GetConnection());
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("RestaurantID", restaurentID);
        cmd.Parameters.AddWithValue("DishID", dishID);
        SqlDataReader dreader = cmd.ExecuteReader();
        dishes = new List<Dishes1>();
        while (dreader.Read())
        {
            dishes.Add(new Dishes1()
            {
                DishID = (int)dreader["DishID"],
                DishName = (string)dreader["DishName"],
                Price = (int)dreader["Price"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return dishes;
}

public List<Cuisine> GetCuisines(int restaurentID, string cousineID)
{
    List<Cuisine> cuisines = null;
    try
    {
        SqlCommand cmd = new SqlCommand("spGetCuisines", GetConnection());
        cmd.CommandType = System.Data.CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("RestaurantID", restaurentID);
        cmd.Parameters.AddWithValue("CuisineID", cousineID);
        SqlDataReader dreader = cmd.ExecuteReader();
        cuisines = new List<Cuisine>();
        while (dreader.Read())
        {
            cuisines.Add(new Cuisine()
            {
                CuisineID = (int)dreader["CuisineID"],
                CuisineName = (string)dreader["CuisineName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return cuisines;
}

public List<Dishes1> GetAllDishes()
{
    List<Dishes1> dishes = null;
    try
    {
        SqlCommand cmd = new SqlCommand("Select DishID, DishName From Dishes1", GetConnection());
        cmd.CommandType = System.Data.CommandType.Text;
        SqlDataReader dreader = cmd.ExecuteReader();
        dishes = new List<Dishes1>();
        while (dreader.Read())
        {
            dishes.Add(new Dishes1()
            {
                DishID = (int)dreader["DishID"],
                DishName = (string)dreader["DishName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return dishes;
}

public List<Cuisine> GetAllCuisine()
{
    List<Cuisine> cuisines = null;
    try
    {
        SqlCommand cmd = new SqlCommand("Select CuisineID,  CuisineName From Cuisine1", GetConnection());
        cmd.CommandType = System.Data.CommandType.Text;
        SqlDataReader dreader = cmd.ExecuteReader();
        cuisines = new List<Cuisine>();
        while (dreader.Read())
        {
            cuisines.Add(new Cuisine()
            {
                CuisineID = (int)dreader["CuisineID"],
                CuisineName = (string)dreader["CuisineName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return cuisines;
}

public List<Facilities1> GetAllFacilities()
{
    List<Facilities1> facilities = null;
    try
    {
        SqlCommand cmd = new SqlCommand("Select FacilityID, FacilityName from Facilities1", GetConnection());
        cmd.CommandType = System.Data.CommandType.Text;
        SqlDataReader dreader = cmd.ExecuteReader();
        facilities = new List<Facilities1>();
        while (dreader.Read())
        {
            facilities.Add(new Facilities1()
            {
                FacilityID = (int)dreader["FacilityID"],
                FacilityName = (string)dreader["FacilityName"]
            });
        }
    }
    catch (Exception ex)
    {
        throw;
    }

    return facilities;
}

} ///// 这里是另一个类:

             public partial class Restaurant : System.Web.UI.Page
       {
public string facility = null;
public string cuis = null;
public string dish = null;
public string location = null;

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        BindListView();
        BindDishesAsCheckBoxes();
    }
}

private void BindListView()
{
    string searchText = this.txtSearch.Text;
    string facilityIDs = hfFacilityID.Value == "" ? "" : hfFacilityID.Value.Remove(hfFacilityID.Value.Length - 1);
    string dishIDs = hfDishID.Value == "" ? "" : hfDishID.Value.Remove(hfDishID.Value.Length - 1);
    string cuisineIDs = hfCuisineID.Value == "" ? "" : hfCuisineID.Value.Remove(hfCuisineID.Value.Length - 1);

    try
    {
        DBAccess objDB = new DBAccess();
        listView.DataSource = objDB.GetAllRestaurents(searchText, dishIDs, facilityIDs, cuisineIDs);
        listView.DataBind();
    }
    catch (Exception ex)
    {

    }
}

private void BindDishesAsCheckBoxes()
{
    try
    {
        DBAccess objdb = new DBAccess();

        //dishes
        chkDishes.DataSource = objdb.GetAllDishes();
        chkDishes.DataBind();

        //cuisines
        chkCuisine.DataSource = objdb.GetAllCuisine();
        chkCuisine.DataBind();

        //facilities
        chkFacilities.DataSource = objdb.GetAllFacilities();
        chkFacilities.DataBind();
    }
    catch (Exception ex)
    {

    }
}

#region itemdatabound

protected void ContactsListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{

    string facilityIDs = hfFacilityID.Value == "" ? "" : hfFacilityID.Value.Remove(hfFacilityID.Value.Length - 1);
    string dishIDs = hfDishID.Value == "" ? "" : hfDishID.Value.Remove(hfDishID.Value.Length - 1);
    string cuisineIDs = hfCuisineID.Value == "" ? "" : hfCuisineID.Value.Remove(hfCuisineID.Value.Length - 1);
    try
    {
        if (e.Item.ItemType == ListViewItemType.DataItem)
        {
            Label lbl1 = (Label)e.Item.FindControl("lblRestaurentID");
            DBAccess objdb = new DBAccess();

            //bind  facility
            Repeater rpFacility = (Repeater)e.Item.FindControl("rptFacility");
            rpFacility.DataSource = objdb.GetFacilities(Convert.ToInt32(lbl1.Text), facilityIDs);
            rpFacility.DataBind();

            //bind  dishes
            Repeater rpDish = (Repeater)e.Item.FindControl("rptDish");
            rpDish.DataSource = objdb.GetDishes(Convert.ToInt32(lbl1.Text), dishIDs);
            rpDish.DataBind();

            //bind  dishes
            Repeater rptCuisine = (Repeater)e.Item.FindControl("rptCuisine");
            rptCuisine.DataSource = objdb.GetCuisines(Convert.ToInt32(lbl1.Text), cuisineIDs);
            rptCuisine.DataBind();
        }
    }
    catch (Exception ex)
    {
        //dvError.Visible = true;
        //lblErrorMessage.Text = ex.Message;
    }
}

#endregion

protected void chkDishes_SelectedIndexChanged(object sender, EventArgs e)
{
    foreach (ListItem item in chkDishes.Items)
    {
        if (item.Selected)
        {
            string id = item.Value;
            hfDishID.Value += id + ",";
            BindListView();
        }
    }
}

protected void chkCuisine_SelectedIndexChanged(object sender, EventArgs e)
{
    foreach (ListItem item in chkCuisine.Items)
    {
        if (item.Selected)
        {
            string id = item.Value;
            hfCuisineID.Value += id + ",";
            BindListView();
        }
    }
}

protected void chkFacilities_SelectedIndexChanged(object sender, EventArgs e)
{
    foreach (ListItem item in chkFacilities.Items)
    {
        if (item.Selected)
        {
            string id = item.Value;
            hfFacilityID.Value += id + ",";
            BindListView();
        }
    }
}

protected void btnSeach_Click(object sender, EventArgs e)
{
    BindListView();
}

}

4

2 回答 2

0

您正在编写动态 SQL,这取决于用户正确输入字符串。我认为爆炸可能是由于字符串创建中的错误而发生的。

要调试我会改变这一行:

 Execute sp_executesql @sql

 print @sql

这将为您提供表达式的原始文本。您可以复制并粘贴它,看看发生了什么。请记住,动态 sql 会很快变得非常混乱,因为您正在将操作转置到您正在从字符串构建的引擎中。

您必须确保您的用户传递我认为的合法变量

' ''valA'', ''valB'', ''ValC'' '

因为在传入本身是 varchar 字段的 varchar 字段数组时,您需要用双引号标记引号。这会带来一个问题,因为您必须确保传入的字段本身是合法的。有些人想出了不同的方法来处理这个问题,除了调试代码的方法之外,我还可以提供一些建议:

老实说,如果您有 SQL Server 2008 或更高版本,我会考虑使用“表类型”来声明可以是表类型的自定义类型。用您要查找的数组填充该表并将其传入。您可以构建在 2008 年之后采用表类型的表函数。函数恕我直言,可能并不总是像 procs 那样执行,但它们非常具有可读性并且可以单独作为对象运行链接到这使得它们非常适合遵循封装和可用性规则。

于 2013-01-31T17:00:17.843 回答
0

我假设您动态构建 的原因@sql是您希望提供一个逗号分隔的 ID 列表作为菜肴、菜肴和设施的标准。

然而,这使得查询不可读。所以不要这样做。

根据您的使用情况,为这些条件中的每一个使用表值参数或为您拆分字符串的拆分函数。

一个简单但可读的拆分函数:

ALTER FUNCTION [dbo].[fnStringSplit] (@list ntext)
         RETURNS @table TABLE (token varchar(4000) collate SQL_Latin1_General_CP1_CI_AS) 
AS
BEGIN
      DECLARE @pos       int,
              @textpos   int,
              @chunklen  smallint,
              @chunk     nvarchar(4000),
              @leftover  nvarchar(4000),
              @token     nvarchar(4000),
              @delimiter nchar(1)

      SET @delimiter = N','
      SET @textpos = 1
      SET @leftover = ''
      WHILE @textpos <= datalength(@list) / 2
      BEGIN
         SET @chunklen = 4000 - len(@leftover)
         SET @chunk = @leftover + substring(@list, @textpos, @chunklen)
         SET @textpos = @textpos + @chunklen

         SET @pos = charindex(@delimiter, @chunk)
         WHILE @pos > 0
         BEGIN
            SET @token = left(@chunk, @pos - 1)
            INSERT @table (token) VALUES(@token)
            SET @chunk = substring(@chunk, @pos + 1, len(@chunk))
            SET @pos = charindex(@delimiter, @chunk)
         END

         SET @leftover = @chunk
      END

      INSERT @table(token) VALUES (@leftover)
      RETURN
END

一旦你重写了查询,更正它应该是微不足道的。

于 2013-01-31T17:05:56.323 回答