【发布时间】:2020-03-04 04:08:23
【问题描述】:
SQL Server 查询如何从参数中选择?我只想根据我的 C# 代码使其成为简单的设置选择列。可能吗?
这是我的存储过程:
ALTER PROCEDURE [dbo].[GetMembersDetailGenerateChanceTop10000]
@EventId nvarchar(255),
@PeriodId nvarchar(255),
@QueryParam nvarchar(1000)
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT TOP 10000 @QueryParam
FROM ign..Chance_Generated cg
INNER JOIN ign..Contact c ON cg.ContactID = c.ContactId
LEFT JOIN ign..CustomerAddress ca ON ca.parentid = cg.contactid
LEFT JOIN ign..new_cardlevelconfig cl ON cl.new_cardlevelconfigid = c.new_cardlevel
LEFT JOIN ign..new_country co ON co.new_countryid = c.new_country
LEFT JOIN ign..new_province po ON po.new_provinceId = c.new_Province
LEFT JOIN ign..StringMap sm ON sm.AttributeValue = c.new_IDType
LEFT JOIN ign..new_city cy ON cy.new_cityId = c.new_CityCounty
LEFT JOIN ign..new_transactionheader th ON cg.New_Name COLLATE DATABASE_DEFAULT = th.new_name COLLATE DATABASE_DEFAULT
WHERE cg.EventId = @EventId
AND (ca.AddressNumber = '1' OR ca.AddressNumber IS NULL)
AND (sm.AttributeName IS NULL OR sm.AttributeName = 'new_idtype')
AND cg.periodId = @PeriodId
QueryParam、EventId、PeriodId 将从 C# 代码中填充。
这是我的 C# 代码:
private List<GenerateModel> getDataTopFromStoreProcedure(string EventId, string PeriodId)
{
// query select parameter
string QueryParam = @"cg.Chance_Number, th.new_name as [th name], dateadd(HOUR,7,th.createdon) as [th createdon],
c.new_Initial, c.FirstName, c.LastName";
string ConnString = GenerateChance.Properties.Settings.Default["DB_ConnectionString"].ToString();
using (SqlConnection conn = new SqlConnection(ConnString))
{
SqlCommand cmd = new SqlCommand();
cmd.CommandText = GetMembersDetailGenerateChanceTop10000;
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandTimeout = 0; //no limit
cmd.Parameters.Clear();
cmd.Parameters.Add(new SqlParameter("QueryParam", QueryParam));
cmd.Parameters.Add(new SqlParameter("EventId", EventId));
cmd.Parameters.Add(new SqlParameter("PeriodId", PeriodId));
cmd.Connection = conn;
if (conn.State == ConnectionState.Open)
conn.Close();
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
list.Add(new GenerateModel
{
ChanceNumber = reader["Chance_Number"].ToString(), //System.IndexOutOfRangeException Error
Receipt = reader["th name"].ToString(),
Date = reader["th createdon"].ToString(),
Initial = reader["new_Initial"].ToString(),
FirstName = reader["FirstName"].ToString(),
LastName = reader["LastName"].ToString(),
});
}
reader.Close();
}
}
return list;
}
我对如何实现他的方法感到困惑,因为我想返回对象模型中的所有选择结果,但总是出错
System.IndexOutOfRangeException : Chance_Number。
老实说,我为什么使用查询选择参数是因为我想从我之前定义的checkedListBox1 中获取值,方法是使用此代码获取所有checkedListBox1 值来确定选择查询。
string QueryParam = "cg.Chance_Number";//auto get chance_number as select mandatory
for (int i = 0; i < checkedListBox1.CheckedItems.Count; i++)
{
QueryParam += ", " + ((clsItemList)checkedListBox1.CheckedItems[i]).Value;
}
【问题讨论】:
-
您不能在这样的参数中传递列名列表。您必须更改存储过程以从中生成 SQL,然后使用 sp_executesql 之类的东西运行它。
-
@juharrdo 你有什么建议如何编辑我的存储过程?
-
您要查找的术语是“动态 SQL”。虽然要小心你传入的内容,以免自己暴露在 SQL 注入中。
-
看看this SO answer 是否有帮助。正如@John 指出的那样 - 这是一把双刃剑,所以要小心
-
@aminvincent,存储过程的 SELECT 必须返回读者正在等待的别名。动态 SELECT 没用。
标签: c# sql-server winforms stored-procedures