我有两个SQL表(SalesCategory和ProductLine),每个表有两列。产品类别不能同时与销售类别和产品系列相关联。但是,用户可以更改,例如,产品类别ABC与销售类别123而不是产品线456相关联。当发生类似这样的情况时,我想从ProductLine SQL表中删除产品类别ABC的记录并更新SalesCategory,其ID为产品类别ABC。但我不知道如何在不创建另一个单独的DELETE函数的情况下执行此操作,并在相关SQL表的save函数内调用它们。我觉得我投入了太多与这两个SQL表相关的函数....
作为重要的附注,产品类别不能与多个产品系列或多个销售类别相关联。
有没有更好的方法来设置代码,所以我没有一堆与两个SQL数据库表相关联的函数?或者这是最好的方式吗?
这是我现在的代码:
//Get current Product Line and Sales Cateogry data for the current Category.
//These two functions are called in the Page_Load
protected string getProductLine()
{
string retVal = "";
try
{
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["AbleCommerce"].ToString()))
{
cn.Open();
SqlCommand cmd = new SqlCommand("SELECT ProductLine FROM ProductLine WHERE uidCategory = @CategoryID", cn);
cmd.Parameters.Add(new SqlParameter("@CategoryID", _CategoryId));
cmd.CommandType = CommandType.Text;
using (IDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
if (reader["ProductLine"].ToString() != "")
{
productLineTxt.Text = reader["ProductLine"].ToString();
retVal = productLineTxt.Text;
}
else
{
retVal = "";
}
}
}
cn.Close();
}
}
catch (Exception ex)
{
//
}
return retVal;
}
protected string getSalesCategory()
{
string retVal = "";
try
{
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["AbleCommerce"].ToString()))
{
cn.Open();
SqlCommand cmd = new SqlCommand("SELECT SalesCat FROM SalesCategory WHERE uidCat = @CategoryID", cn);
cmd.Parameters.Add(new SqlParameter("@CategoryID", _CategoryId));
cmd.CommandType = CommandType.Text;
using (IDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
if (reader["SalesCat"].ToString() != "")
{
salesCatTxt.Text = reader["SalesCat"].ToString();
retVal = salesCatTxt.Text;
}
else
{
retVal = "";
}
}
}
cn.Close();
}
}
catch (Exception x)
{
//
}
return retVal;
}
//These two functions are called in the saveSalesCategory() and saveProductLine() functions respectively. They determine if those save functions should perform an UPDATE or INSERT. This is meant to prevent a Product Category from having association with more than one Product Line or Sales Category
protected bool salesCatExists()
{
bool retVal = true;
try
{
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["AbleCommerce"].ToString()))
{
cn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandText = "SELECT COUNT(*) AS 'Exists' FROM SalesCategory WHERE uidCat = @CategoryID";
cmd.Parameters.Add(new SqlParameter("@CategoryID", _CategoryId));
cmd.Parameters.Add(new SqlParameter("@SalesCategory", salesCatTxt.Text));
cmd.CommandType = CommandType.Text;
using (IDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
if (Convert.ToInt32(reader["Exists"]) == 0)
{
retVal = false;
}
else
{
retVal = true;
}
}
}
cn.Close();
}
}
catch (Exception x)
{
//
}
return retVal;
}
protected bool productLineExists()
{
bool retVal = true;
try
{
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["AbleCommerce"].ToString()))
{
cn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.CommandText = "SELECT COUNT(*) AS 'Exists' FROM ProductLine WHERE uidCategory = @CategoryID";
cmd.Parameters.Add(new SqlParameter("@CategoryID", _CategoryId));
cmd.Parameters.Add(new SqlParameter("@ProductLine", productLineTxt.Text));
cmd.CommandType = CommandType.Text;
using (IDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
if (Convert.ToInt32(reader["Exists"]) == 0)
{
retVal = false;
}
else
{
retVal = true;
}
}
}
cn.Close();
}
}
catch (Exception x)
{
//
}
return retVal;
}
//Save new or update old Product Line and Sales Category data for the current Category
protected void saveProductLine()
{
try
{
string update1 = "UPDATE ProductLine SET ProductLine = @ProductLine WHERE uidCategory = @CategoryID";
string update2 = "UPDATE ProductLine SET ProductLine = '' AND uidCategory = '' WHERE uidCategory = @CategoryID";
string insert = "INSERT INTO ProductLine (uidCategory, ProductLine) VALUES(@CategoryID, @ProductLine)";
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["AbleCommerce"].ToString()))
{
cn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = cn;
cmd.Parameters.Add(new SqlParameter("@CategoryID", _CategoryId));
cmd.Parameters.Add(new SqlParameter("@ProductLine", productLineTxt.Text));
cmd.CommandType = CommandType.Text;
if (getProductLine() == "")
{
cmd.CommandText = insert;
}
else
{
productLineTxt.Text = getProductLine();
cmd.CommandText = update;
}
cmd.ExecuteNonQuery();
cn.Close();
}
}
catch (Exception ex)
{
//
}
}
protected void saveSalesCategory()
{
string update = "UPDATE SalesCategory SET SalesCat = @SalesCategory WHERE uidCat = @CategoryID";
string insert = "INSERT INTO SalesCategory (uidCat, SalesCat) VALUES(@CategoryID, @SalesCategory)";
try
{
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings["AbleCommerce"].ToString()))
{
cn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Parameters.Add(new SqlParameter("@CategoryID", _CategoryId));
cmd.Parameters.Add(new SqlParameter("@SalesCategory", salesCatTxt.Text));
cmd.Connection = cn;
cmd.CommandType = CommandType.Text;
if (salesCatExists() == false)
{
cmd.CommandText = insert;
}
else
{
cmd.CommandText = update;
}
cmd.ExecuteNonQuery();
cn.Close();
}
}
catch (Exception x)
{
//
}
}
答案 0 :(得分:1)
您可以查看SQL MERGE语句。我不确定我是否完全理解您希望做的事情足以提供一个代码示例,说明它可能对您有何帮助,但听起来它可能会像您的目标一样。
例如,它允许您在给定一个键或一组键的情况下检查一个表(无论是实际表还是表值变量),然后在记录匹配时或在它们发生时执行操作不配。我想我可以举一个简单的例子:
此查询可以处理saveSalesCategory
方法中的大部分逻辑:
MERGE SalesCategory AS T
USING (VALUES ((@CategoryID, @SalesCategory)) AS S (uidCat, SalesCat)
ON (T.uidCat = S.uidCat)
WHEN MATCHED THEN
UPDATE SET SalesCat = S.SalesCat
WHEN NOT MATCHED THEN
INSERT (uidCat, SalesCat) VALUES (S.uidCat, S.SalesCat)
正如您所注意到的,它会检查是否存在任何记录,然后相应地插入或更新。这样就无需运行salesCatExists()
并使用多个TSQL查询。
我认识到这并没有回答你的问题(我认为?)但是我希望它至少可以引导你朝着正确的方向前进,因为我仍然不太确定你到底在想什么对
答案 1 :(得分:0)
您无法在一个命令中更新一个表并删除另一个表。似乎数据结构是你在这里最激烈的。如果您的ProductCategory表有一个ReferenceType列,这将非常简单。您可以在一次传递中更新ReferenceType和外键值。通过它们将这些组合在一起,您也将面临参考完整性的挑战,因为ProductCategory中的值对于一个或另一个表来说是异类,具体取决于它的类型。
答案 2 :(得分:0)
您的代码示例看起来似乎没有尝试执行您描述的所有内容。也许你还没有进入删除部分。我认为一些存储过程可能会有所帮助。我将你的几个方法压缩成一个存储过程,你可以为产品线做同样的事情。我只是不确定在哪里放DELETE语句。这是正确的方向吗?如果是这样,我们可以找出删除的位置;)
CREATE PROCEDURE SaveSalesCategory
@CategoryID INT ,
@SalesCategory INT
AS
BEGIN
DECLARE @SalesCatCount INT = ( SELECT COUNT(*) AS 'Exists'
FROM SalesCategory
WHERE uidCat = @CategoryID
)
IF @SalesCatCount = 0
BEGIN
INSERT INTO SalesCategory
( uidCat, SalesCat )
VALUES ( @CategoryID, @SalesCategory )
END
ELSE
BEGIN
UPDATE SalesCategory
SET SalesCat = @SalesCategory
WHERE uidCat = @CategoryID
END
END
GO
答案 3 :(得分:0)
使用OUTPUT子句(MSDN)
DELETE ProductLine
WHERE uidCategory = @CategoryID
OUTPUT column1,column2,etc INTO SalesCategory
或
DELETE SalesCategory
WHERE uidCategory = @CategoryID
OUTPUT column1,column2,etc INTO ProductLine
答案 4 :(得分:0)
您可以在这两个表上设置一个触发器,这样当您插入新记录或更新现有记录时,数据库会查找该类别的其他表并删除该记录。
并非所有参数都在您的示例代码中使用,而且它有点长,所以我不认为这些代码完全符合您的需要,但我认为应该有效。
CREATE TRIGGER dbo.TRG_SalesCategory_RECORD
ON SalesCategory
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
Delete from ProductLine
Where CategoryID = (select CategoryID from INSERTED)
END
GO
CREATE TRIGGER dbo.TRG_ProductLine_RECORD
ON ProductLine
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON;
Delete from SalesCategory
Where CategoryID = (select CategoryID from INSERTED)
END
GO