Adding Primary Keys and Foreign Keys to a Table

此博客使用C#代码实现从数据库提取数据。通过OleDb连接数据库,执行SELECT语句提取BookList和BookAuthors表数据存入DataSet。对表设置主键、唯一约束和外键约束,最后将表内容、约束信息绑定到DataGrid显示,还使用DataView展示表数据。

<script language="C#" runat="server">

 void Page_Load(Object sender, EventArgs e)
 {

  // get connection string from ../global/connect-strings.ascx user control
  string strConnect = ctlConnectStrings.OLEDBConnectionString;
  outConnect.InnerText = strConnect; // and display it

  // specify the SELECT statement to extract the BookList data
  string strSelectBooks = "SELECT * FROM BookList WHERE ISBN LIKE '18610033%'";
  outSelectBooks.InnerText = strSelectBooks;   // and display it

  // specify the SELECT statement to extract the BookAuthor data
  string strSelectAuthors = "SELECT * FROM BookAuthors WHERE ISBN LIKE '18610033%'";
  outSelectAuthors.InnerText = strSelectAuthors;   // and display it

  // declare a variable to hold a DataSet object
  DataSet objDataSet = new DataSet();

  try
   {
   // create a new Connection object using the connection string
   OleDbConnection objConnect = new OleDbConnection(strConnect);

   // create a new Command object
   OleDbCommand objCommand = new OleDbCommand();

   // set the properties
   objCommand.Connection = objConnect;
   objCommand.CommandType = CommandType.Text;
   objCommand.CommandText = strSelectBooks;

   // create a new DataAdapter object
   OleDbDataAdapter objDataAdapter = new OleDbDataAdapter();
   // and assign the Command object to it
   objDataAdapter.SelectCommand = objCommand;

   // get the data from the "BookList" table in the database and
   // put it into a table named "Books" in the DataSet object
   objDataAdapter.Fill(objDataSet, "Books");

   // change the SELECT statement in the Command object
   objCommand.CommandText = strSelectAuthors;
   // then get data from "BookAuthors" table into the DataSet
   objDataAdapter.Fill(objDataSet, "Authors");
  }
  catch (Exception objError)
  {
   // display error details
   outError.InnerHtml = "<b>* Error while accesing data</b>.<br />"
     + objError.Message + "<br />" + objError.Source;
   return;  //  and stop execution

  }

  // now that the DataSet is filled, we can modify the tables it contains
  // declare variables to refer to the DataTable and a DataColumn objects
               
  DataTable objParentTable = objDataSet.Tables["Books"];//父表
  DataTable objChildTable = objDataSet.Tables["Authors"];//子表
  DataColumn objParentColumn = objParentTable.Columns["ISBN"];//父表的ISBN列
  DataColumn objChildColumn = objChildTable.Columns["ISBN"];//子表ISBN列

  // create a new UniqueConstraint object and add to Constraints collection
                //创建主键约束
  UniqueConstraint objUnique = new UniqueConstraint("Unique_ISBN", objParentColumn);//Unique_ISBN是约束名,objParentColumn是主键约束列
  objParentTable.Constraints.Add(objUnique);//添加约束
      
  // prevent the column from accepting Null values
  objParentColumn.AllowDBNull = false;

  // create an array of columns containing this column only
               
  DataColumn[] objColumnArray = new DataColumn[1];
  objColumnArray[0] = objParentColumn;

  // and set this array as the columns for the Primary Key of the table
               //指定主键(是一个DataColumn数组,保证只有唯一标号。此处只有ISBN一列)
  objParentTable.PrimaryKey = objColumnArray;

  // now we can process the child table named "Authors"
  // create an array of columns containing the ISBN and Lastname columns
                
  objColumnArray = new DataColumn[2];
  objColumnArray[0] = objChildColumn;    // the ISBN column
  objColumnArray[1] = objChildTable.Columns["Lastname"];

  // prevent either of these columns containing Null
  objColumnArray[0].AllowDBNull = false;
  objColumnArray[1].AllowDBNull = false;
  
  // set this column array as the primary key
             //指定主键(由ISBN和Lastname两列组成的数组)
  objChildTable.PrimaryKey = objColumnArray;

  // create a new ForeignKeyConstraint object
                //指定外键
  ForeignKeyConstraint objFKey = new ForeignKeyConstraint("FK_BookAuthors",  objParentColumn, objChildColumn);
  // set the "update" properties
  objFKey.DeleteRule = Rule.Cascade;//级联
  objFKey.UpdateRule = Rule.Cascade;

  // and add it to the Constraints collection
  objChildTable.Constraints.Add(objFKey);

  // --------------------------------------------------------------
  // now we're ready to display the contents of the DataSet object
  // bind the collection of Tables to the first DataGrid on the page
  dgrTables.DataSource = objDataSet.Tables;
  dgrTables.DataBind();

  // bind the collection of Constraints to the second DataGrid on the page
  dgrBookCons.DataSource = objDataSet.Tables["Books"].Constraints;
  dgrBookCons.DataBind();

  // bind the collection of Constraints to the third DataGrid on the page
  dgrAuthorCons.DataSource = objDataSet.Tables["Authors"].Constraints;
  dgrAuthorCons.DataBind();

  // create a DataView object to use with the tables in the DataSet
  DataView objDataView = new DataView();

  // get the default view of the Books table into the DataView object
  objDataView = objDataSet.Tables["Books"].DefaultView;
  // and bind it to the next DataGrid on the page
  dgrBooksData.DataSource = objDataView;
  dgrBooksData.DataBind();

  // then do the same for the Authors table
  objDataView = objDataSet.Tables["Authors"].DefaultView;
  dgrAuthorsData.DataSource = objDataView;
  dgrAuthorsData.DataBind();

}
</script>


 

`JobDefineCheckException: Adding transform to multi-table source is not supported` 是在数据集成或ETL(抽取、转换、加载)任务中常见的错误信息,特别是在使用某些数据流处理框架(如Apache Beam、Flink或企业级数据集成工具)时。该错误表明尝试在一个多表源(multi-table source)上添加转换操作(transform),但该框架或工具不支持这种操作。 ### 原因分析 1. **多表源的限制**:多表源通常用于从多个数据表中并行读取数据,其结构设计为只支持原始数据的读取,而不支持在源阶段直接进行复杂的转换操作[^1]。 2. **框架设计约束**:某些框架为了保证数据一致性、性能优化或执行计划的稳定性,禁止在源操作中嵌入转换逻辑。 3. **类型或结构不匹配**:当尝试添加的转换依赖于特定的数据结构或字段类型,而多表源未能提供统一的 schema 时,也会触发此类异常。 ### 解决方案 #### 1. 将转换操作移至下游操作中 避免在多表源节点上直接添加转换,而是将其移至后续的 `map` 或 `transform` 阶段。例如: ```python # 错误写法:在源操作中添加转换 source = pipeline.read_from_multi_table(sources).map(transform_fn) # 正确写法:将转换移至下游 source = pipeline.read_from_multi_table(sources) transformed = source.map(transform_fn) ``` #### 2. 使用统一的预处理源 如果多个表具有相似结构,可以考虑在源端使用统一的预处理逻辑,例如通过视图、中间表或自定义读取器将多个表合并为一个逻辑源,从而支持转换操作。 #### 3. 自定义源转换器 对于支持自定义源的框架(如 Apache Beam),可以实现一个自定义的 `PTransform`,在读取多表数据的同时执行必要的转换逻辑。 ```java // 示例(Java + Apache Beam) public class MultiTableTransform extends PTransform<PCollection<Row>, PCollection<TransformedRow>> { @Override public PCollection<TransformedRow> expand(PCollection<Row> input) { return input.map(new SerializableFunction<Row, TransformedRow>() { @Override public TransformedRow apply(Row input) { return transformLogic(input); } }); } } ``` #### 4. 使用中间集合或缓存 在读取多表源后,立即将其缓存为一个中间集合(如 `PCollection`),然后在该中间集合上执行所有转换操作。 #### 5. 检查框架文档与版本兼容性 确保所使用的框架版本支持多表源上的转换操作。某些框架可能在特定版本中引入了对源转换的支持,或者提供了替代的 API。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值