我會建議這是一個可能的解決方案。如果有人感興趣,我會對這個優化版本感興趣。感謝@Ken的指針。 (我不知道如何爲SO格式化這個格式,對不起)。
internal static void UpdateDxLibraryTx(PhysicalExam.DX newdx, PhysicalExam.DX olddx)
{
String Unique_Violation = "23505";
// nothing to change.
if (olddx.description == null) return;
PhysicalExam.DX oldDx = (PhysicalExam.DX)olddx;
// the server structure was created in MainWindow on initialization.
string connect = server.connection_string;
string update = " update icd9 set cicd9='" + newdx.icd9 + "', cdesc= '" + newdx.description.ToLower().Trim() + "'" +
" ,chronic ='" + newdx.chronic + "' ,modified='" + DateTime.Now + "'" +
" where cicd9 ='" + oldDx.icd9 + "'" +
" and trim(cdesc) ='" + oldDx.description.ToLower().Trim() + "' and chronic ='" + oldDx.chronic + "';";
string getchildtables = " select confrelid::regclass, af.attname as fcol, "+
" conrelid::regclass, a.attname as col "+
" from pg_attribute af, pg_attribute a, "+
" (select conrelid,confrelid,conkey[i] as conkey, confkey[i] as confkey "+
" from (select conrelid,confrelid,conkey,confkey, "+
" generate_series(1,array_upper(conkey,1)) as i "+
" from pg_constraint where contype = 'f') ss) ss2 "+
" where af.attnum = confkey and af.attrelid = confrelid and "+
" a.attnum = conkey and a.attrelid = conrelid "+
" AND confrelid::regclass = 'ICD9'::regclass AND (af.attname = 'cicd9' OR af.attname ='cdesc');";
string sf = " update {0} set cicd9= '"+ newdx.icd9 +"' ,cdesc= '"+ newdx.description.ToLower().Trim() +"'," +
" chronic = '"+newdx.chronic+"', modified= '"+ DateTime.Now +"'" +
" where cicd9 = '"+ oldDx.icd9 +"' and trim(cdesc)= '"+ oldDx.description.ToLower().Trim() +"' and chronic ='"+ oldDx.chronic +"';";
string delete = "Delete from icd9 where trim(cicd9) = '" + oldDx.icd9.Trim() + "'" +
" and trim(cdesc)='" + oldDx.description.Trim() + "' and chronic = '"+ oldDx.chronic +"';";
// NpsqlConnection is unmanaged code...should use a using() block.
using (NpgsqlConnection pgConnection = new NpgsqlConnection(connect))
{
try
{
pgConnection.Open();
// Connection successful
// Create a new transaction
using (NpgsqlTransaction pgTransaction = (NpgsqlTransaction)pgConnection.BeginTransaction())
{
try
{
using (NpgsqlCommand updateCMD = new NpgsqlCommand(update, pgConnection, pgTransaction))
{
updateCMD.ExecuteNonQuery();
}
//Commit transaction. Hope it works! Will fail for unique key violation.
pgTransaction.Commit();
}
catch (NpgsqlException ex)
{
pgTransaction.Rollback();
if (ex.Code == Unique_Violation)
{
try
{
using (NpgsqlDataAdapter children = new NpgsqlDataAdapter(getchildtables,pgConnection))
{
DataSet ds = new DataSet();
children.Fill(ds);
DataView dv = new DataView();
dv.Table = ds.Tables[0];
foreach (DataRowView drv in dv)
{
string childtable = (string)drv[2];
string updatechild = String.Format(sf, childtable);
NpgsqlCommand updateCMD = new NpgsqlCommand(updatechild, pgConnection);
int k = updateCMD.ExecuteNonQuery();
}
/* all tables now point to new value. remove old value from parent table. */
NpgsqlCommand deleteCMD = new NpgsqlCommand(delete, pgConnection);
int j = deleteCMD.ExecuteNonQuery();
}
}
catch (NpgsqlException ex1)
{
string error = ex1.Message;
throw;
}
}
else
throw;
}
}
}
catch (NpgsqlException ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (Exception ex)
{
string s = ex.Message;
throw;
}
}
}
我想你會以錯誤的方式去做。如果您打算讓「主」表包含拼寫,則應該在主表中引入一個仿真關鍵字(身份或類似關鍵字),並將其用作關聯表中的FK。重複描述是可以避免的。對於您的特定問題,如果在更新時遇到重複的值衝突,那是因爲數據會導致一個(您可能會修正拼寫錯誤,其中存在非拼寫錯誤記錄),然後您應該更新數據手動/通過觸發器。 –
@ AllanS.Hansen有道理。我需要更多地研究觸發器。一個例子真的會有幫助。 –