MSSQL中的数组-Table类型.

本文详细介绍了SQL Server中的表变量,包括其定义、语法及使用场景。表变量作为一种特殊的数据类型,适用于临时存储结果集,尤其适合在函数、存储过程或批处理中使用。文章对比了表变量与临时表的区别,强调了表变量的优点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

table  
  一种特殊的数据类型,用于存储结果集以供后续处理。该数据类型主要用于临时存储一组行,这些行将作为表值函数的结果集返回。  
   
  语法  
   
   
  说明     使用   DECLARE   @local_variable   声明   table   类型的变量。  
   
   
  table_type_definition   ::=  
          TABLE   (   {   column_definition   |   table_constraint   }   [   ,...n   ]   )    
   
  column_definition   ::=  
          column_name   scalar_data_type  
          [   COLLATE   collation_definition   ]  
          [   [   DEFAULT   constant_expression   ]   |   IDENTITY   [   (   seed   ,   increment   )   ]   ]  
          [   ROWGUIDCOL   ]  
          [   column_constraint   ]   [   ...n   ]    
   
  column_constraint   ::=  
          {   [   NULL   |   NOT   NULL   ]  
          |   [   PRIMARY   KEY   |   UNIQUE   ]  
          |   CHECK   (   logical_expression   )  
          }    
   
  table_constraint   ::=    
          {   {   PRIMARY   KEY   |   UNIQUE   }   (   column_name   [   ,...n   ]   )  
          |   CHECK   (   search_condition   )    
          }    
   
  参数  
  table_type_definition  
   
  与   CREATE   TABLE   中定义表所用的信息子集相同的信息子集。表声明包括列定义、名称、数据类型和约束。允许的约束类型仅为   PRIMARY   KEY、UNIQUE   KEY   和   NULL。  
   
  有关语法的更多信息,请参见   CREATE   TABLE、CREATE   FUNCTION   和   DECLARE   @local_variable。  
   
  collation_definition  
   
  是由   Microsoft®   Windows™   区域设置和比较风格、Windows   区域设置和二进制表示法或   Microsoft   SQL   Server™   排序规则组成的列的排序规则。  
   
  注释  
  可将函数和变量声明为   table   类型。table   变量可用于函数、存储过程和批处理中。  
   
  尽可能使用表变量而不使用临时表。table   变量有以下优点:    
   
  table   变量的行为类似于局部变量,有明确定义的作用域。该作用域为声明该变量的函数、存储过程或批处理。    
  在其作用域内,table   变量可像常规表那样使用。该变量可应用于   SELECT、INSERT、UPDATE   和   DELETE   语句中用到表或表的表达式的地方。但是,table   不能用在下列语句中:  
   
  INSERT   INTO   table_variable   EXEC   存储过程。  
   
  SELECT   select_list   INTO   table_variable   语句。  
   
  在定义   table   变量的函数、存储过程或批处理结束时,自动清除   table   变量。  
   
  在存储过程中使用表变量与使用临时表相比,减少了存储过程的重新编译量。  
   
   
  涉及表变量的事务只在表变量更新期间存在。这样就减少了表变量对锁定和记录资源的需求。    
  不支持在表变量之间进行赋值操作。另外,由于表变量作用域有限,并且不是持久数据库的一部分,因而不受事务回滚的影响。  

摘自:http://topic.youkuaiyun.com/t/20060927/12/5051395.html
./bin/flink run -d -t yarn-per-job \ -Dyarn.application.name="flinkcdc_prod_old_smpcdb_3" \ -Dyarn.application.queue="hive" \ -Dstate.backend=rocksdb \ -Dstate.externalize-checkpoints=true \ -Dexecution.checkpointing.externalized-checkpoint-retention=RETAIN_ON_CANCELLATION \ -Dexecution.checkpointing.interval=180s \ -Dexecution.checkpointing.timeout=7200s \ -Dexecution.checkpointing.min-pause=60s \ -Dexecution.checkpointing.max-concurrent-checkpoints=1 \ -Dstate.checkpoints.dir=hdfs://hadoop102:8020/flink_ck/offline/prod_old_smpcdb \ --allowNonRestoredState \ -Dparallelism.default=4 \ -Djobmanager.memory.process.size=2048m \ -Dtaskmanager.memory.process.size=5120m \ -Dtaskmanager.numberOfTaskSlots=2 \ -c org.apache.doris.flink.tools.cdc.CdcTools \ /opt/module/flink-1.17.2-sql-cdc/lib/flink-doris-connector-1.17-1.6.2.jar \ oracle-sync-database \ --database prod_old_smpcdb \ --oracle-conf hostname=10.1.9.2 \ --oracle-conf port=1521 \ --oracle-conf database-name=PMS2 \ --oracle-conf username=pms \ --oracle-conf password="SRX3yak#8" \ --oracle-conf schema-name=PMS \ --oracle-conf debezium.database.history.store.only.captured.tables.ddl=true \ --oracle-conf debezium.log.miner.enabled=false \ --oracle-conf debezium.snapshot.mode=initial_only \ --oracle-conf debezium.snapshot.fetch.size=20000 \ --oracle-conf debezium.column.mapping="CLOB:STRING,BLOB:STRING" \ --oracle-conf debezium.snapshot.checkpoint.interval.ms=0 \ --oracle-conf debezium.transforms=encodeBlob \ --oracle-conf debezium.transforms.encodeBlob.format=base64 \ --oracle-conf debezium.database.url="jdbc:oracle:thin:@//10.1.9.2:1521/PMS" \ --including-tables "EXP_PHOTO" \ --sink-conf fenodes=10.210.31.92:18030 \ --sink-conf username=root \ --sink-conf password=zjj000000 \ --sink-conf jdbc-url=jdbc:mysql://10.210.31.92:9030 \ --sink.buffer-size=100M \ --sink.buffer-flush.interval=60000 \ --sink-conf sink.enable-2pc=false \ --sink-conf sink.label-prefix=label_cdc_prod_old_smpcdb_340 \ --sink-conf sink.stream-load.timeout=7200 \ --sink-conf sink.connect.timeout.ms=60000 \ --sink-conf sink.request.timeout.ms=3600000 \ --table-conf replication_num=1 目前是flink doris connetct 来采集表中大字段
最新发布
07-26
<think>我们正在解决Flink Doris Connector通过Oracle CDC同步时大字段(CLOB/BLOB)为空的问题。根据用户提供的引用和之前的分析,我们需要重点关注Oracle CDC连接器对大字段的支持以及Flink Doris Connector的数据映射处理。 引用[1]指出:Flink的schema定义仅声明如何将物理列从外部系统映射到Flink,映射规则取决于连接器实现。引用[2]提到Oracle中expr不能使用BFILE、BLOB、CLOB等类型,这提示我们在CDC同步中需要特殊处理这些类型。 结合之前的分析,以下是解决方案: ### 解决方案步骤 #### 1. **配置Oracle CDC源以捕获大字段** - 使用Debezium Oracle Connector时,必须显式启用LOB支持并设置相关参数。 - 在Flink CDC作业中,配置`debezium`属性: ```java Properties debeziumProperties = new Properties(); debeziumProperties.setProperty("snapshot.mode", "initial"); debeziumProperties.setProperty("lob.enabled", "true"); // 关键:启用LOB支持 debeziumProperties.setProperty("column.include.list", "SCHEMA_NAME.TABLE_NAME.CLOB_COLUMN,BLOB_COLUMN"); // 包含大字段列 // 调整事件大小限制(根据实际字段大小调整) debeziumProperties.setProperty("max.request.size", "10485760"); // 10MB debeziumProperties.setProperty("message.key.columns", "SCHEMA_NAME.TABLE_NAME:PRIMARY_KEY_COLUMN"); OracleSource<String> oracleSource = OracleSource.<String>builder() .hostname("oracle_host") .port(1521) .database("ORCL") .username("user") .password("password") .debeziumProperties(debeziumProperties) .deserializer(new JsonDebeziumDeserializationSchema()) // 使用JSON格式 .build(); ``` - 注意:`column.include.list`需要指定包含大字段的列,格式为`SCHEMA.TABLE.COLUMN`(区分大小写)。 #### 2. **在Flink中处理大字段数据** - 由于Debezium会将CLOB/BLOB字段转换为字符串(Base64编码)或字节数组,在Flink中需要进行转换。 - 如果使用`JsonDebeziumDeserializationSchema`,CDC事件会以JSON字符串形式传递。我们需要解析JSON并提取大字段: ```java DataStream<RowData> stream = env.fromSource(oracleSource, WatermarkStrategy.noWatermarks(), "Oracle Source") .flatMap(new FlatMapFunction<String, RowData>() { @Override public void flatMap(String value, Collector<RowData> out) throws Exception { // 解析JSON字符串 JsonObject json = JsonParser.parseString(value).getAsJsonObject(); JsonObject after = json.getAsJsonObject("after"); // 提取CLOB字段(假设在CDC事件中CLOB字段被转换为Base64字符串) String clobData = after.get("CLOB_COLUMN").getAsString(); // 将Base64字符串解码为原始字符串(如果是文本) // 注意:如果CLOB存储的是文本,则可以直接使用;如果是二进制数据,则按BLOB处理 String decodedClob = new String(Base64.getDecoder().decode(clobData), StandardCharsets.UTF_8); // 构建RowData对象,这里省略其他字段 GenericRowData row = new GenericRowData(2); row.setField(0, ...); // 主键等其他字段 row.setField(1, StringData.fromString(decodedClob)); out.collect(row); } }); ``` - 对于BLOB字段,处理方式类似,但需要根据实际需求决定是否转换为Doris支持的格式(如十六进制字符串或Base64字符串)。 #### 3. **配置Doris表以接收大字段** - Doris中,CLOB可以映射为`VARCHAR(65533)`或`STRING`类型(Doris 1.2+支持),BLOB可以映射为`STRING`(存储Base64编码)或`BITMAP`(如果适用)等。 - 创建Doris表示例: ```sql CREATE TABLE doris_table ( id BIGINT, clob_column STRING, -- 使用STRING类型存储大文本 blob_column STRING -- 存储Base64编码的二进制数据 ) ENGINE=OLAP DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 10 PROPERTIES ( "replication_num" = "1" ); ``` #### 4. **配置Flink Doris Sink** - 在Flink Doris Sink中,确保字段映射正确,并设置合适的序列化格式: ```java DorisOptions dorisOptions = DorisOptions.builder() .setFenodes("FE_HOST:8030") .setTableIdentifier("db.doris_table") .setUsername("doris_user") .setPassword("doris_password") .build(); DorisExecutionOptions executionOptions = DorisExecutionOptions.builder() .setLabelPrefix("doris_label") // 确保label唯一性 .setStreamLoadProp("format", "json") // 使用JSON格式传输 .setStreamLoadProp("strip_outer_array", "true") // 去除JSON外层数组 .build(); // 使用RowDataSerializer RowType rowType = ...; // 根据Doris表结构构建RowType DorisSerializer serializer = new DorisRowDataSerializer(rowType, dorisOptions.getTableIdentifier()); DorisSink<RowData> dorisSink = DorisSink.<RowData>builder() .setDorisOptions(dorisOptions) .setDorisExecutionOptions(executionOptions) .setSerializer(serializer) .build(); stream.sinkTo(dorisSink); ``` #### 5. **性能调优与监控** - **内存调整**:在Flink任务管理器中增加内存,防止大字段导致OOM: ```yaml # flink-conf.yaml taskmanager.memory.process.size: 4096m ``` - **批处理大小**:在Doris Sink中调整批量写入大小: ```java executionOptions = DorisExecutionOptions.builder() .setBufferSize(1024 * 1024) // 1MB .setBufferCount(3) .setCheckInterval(3000) .setMaxRetries(3) .build(); ``` - **监控**:通过Flink Web UI观察背压情况,并在Doris中查看导入状态(`SHOW LOAD WHERE label='doris_label...'`)。 ### 备选方案:使用TapData工具 如果上述步骤仍无法解决问题,或需要更简便的同步方式,可考虑引用[3]提到的TapData工具。它提供图形化界面和内置的Oracle到Doris连接器,支持大字段同步,无需编码: 1. 在TapData中创建Oracle和Doris连接。 2. 选择要同步的表,并在映射规则中启用大字段处理。 3. 启动实时同步任务。 ### 注意事项 - **Oracle CDC连接器版本**:确保使用支持大字段的Debezium版本(如1.9+)。 - **数据类型转换**:CLOB/BLOB在CDC事件中的表示方式(Base64或十六进制)需与Flink处理逻辑一致。 - **Doris版本**:Doris 1.2+对STRING类型支持更好,可存储最大2GB的文本数据。 通过以上步骤,应能解决大字段同步为空的问题。如果问题仍然存在,请检查Debezium日志和Flink任务日志,确认大字段是否在CDC事件中被正确捕获。 §§相关问题§§ 1. 如何监控和优化Flink CDC作业的吞吐量? 2. Doris中如何处理超长字符串(超过1MB)的存储和查询? 3. 使用TapData同步数据时,如何保证端到端的数据一致性? [^1]: Flink SQL CREATE TABLE语句的映射规则说明。 [^2]: Oracle中expr的限制,提示大字段需要特殊处理。 [^3]: TapData作为替代方案,提供简便的Oracle到Doris同步。 [^4]: Flink CBO优化器可能影响执行计划,但与大字段问题关联较小。</think>### Flink Doris Connector Oracle CDC 同步 CLOB/BLOB 字段为空解决方案 针对 Oracle CDC 同步 CLOB/BLOB 字段到 Doris 为空的问题,结合引用信息和实际经验,提供以下完整解决方案: --- #### 一、核心问题诊断(基于引用分析) 1. **Oracle CDC 限制** Oracle 的 `expr` 不支持直接操作 `CLOB/BLOB` 类型字段(引用[2]),导致 CDC 捕获时可能忽略或截断这些字段。 2. **Flink 映射机制** Flink 的 schema 映射依赖于连接器实现(引用[1]),Oracle CDC 默认不处理大字段的完整映射。 3. **Doris 类型兼容** Doris 的 `VARCHAR` 最大支持 65533 字符(引用[1]),超长 CLOB 需特殊处理。 --- #### 二、完整解决方案 ##### 步骤 1:启用 Oracle CDC 大字段支持 在 Debezium 配置中显式启用 LOB 处理: ```properties # Debezium Oracle 连接器配置 debezium.source.connector.class=io.debezium.connector.oracle.OracleConnector debezium.source.database.hostname=oracle-host debezium.source.database.port=1521 debezium.source.database.user=user debezium.source.database.password=pass debezium.source.database.dbname=ORCL debezium.source.table.include.list=SCHEMA.TABLE debezium.source.lob.enabled=true # 关键:启用大字段支持 debezium.source.column.include.list=SCHEMA.TABLE.CLOB_COL,SCHEMA.TABLE.BLOB_COL debezium.source.max.request.size=10485760 # 扩大事件大小至10MB ``` ##### 步骤 2:Flink 数据处理层优化 ```java // 自定义反序列化器处理大字段 public class CustomDebeziumDeserializer implements DebeziumDeserializationSchema<RowData> { @Override public void deserialize(SourceRecord record, Collector<RowData> out) { Struct value = (Struct) record.value(); Struct after = value.getStruct("after"); // 显式处理 CLOB 字段 String clobData = after.getString("CLOB_COL"); if (clobData == null) { clobData = ""; // 防 null 处理 } else if (clobData.length() > 65533) { clobData = clobData.substring(0, 65533); // Doris VARCHAR 截断 } // BLOB 转 Base64 字符串 byte[] blobBytes = after.getBytes("BLOB_COL"); String blobData = (blobBytes != null) ? Base64.getEncoder().encodeToString(blobBytes) : ""; // 构建 RowData 输出 GenericRowData row = new GenericRowData(2); row.setField(0, StringData.fromString(clobData)); row.setField(1, StringData.fromString(blobData)); out.collect(row); } } ``` ##### 步骤 3:Doris 表结构优化 ```sql CREATE TABLE doris_table ( id BIGINT, clob_col VARCHAR(65533) COMMENT '存储截断后的CLOB', blob_col TEXT COMMENT '存储Base64编码的BLOB' ) ENGINE=OLAP DUPLICATE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 10 PROPERTIES ( "replication_num" = "3", "storage_format" = "V2" ); ``` ##### 步骤 4:Flink Doris Sink 配置 ```java DorisSink<RowData> sink = DorisSink.<RowData>builder() .setDorisOptions(DorisOptions.builder() .setFenodes("doris-fe:8030") .setTableIdentifier("db.doris_table") .setUsername("user") .setPassword("pass") .build()) .setDorisExecutionOptions(DorisExecutionOptions.builder() .setLabelPrefix("doris-cdc-") .setStreamLoadProp("format", "json") // JSON格式支持大字段 .setStreamLoadProp("strip_outer_array", "true") .build()) .setSerializer(new SimpleRowDataSerializer( // 自定义序列化器 TableSchema.builder() .field("clob_col", DataTypes.STRING()) .field("blob_col", DataTypes.STRING()) .build() )) .build(); ``` --- #### 三、备选方案:使用 TapData(引用[3]) 对于复杂场景,推荐使用专业数据同步工具: ```mermaid graph LR A[Oracle] -->|CDC| B(TapData Agent) B -->|实时同步| C[Doris] ``` 优势: 1. 自动处理 CLOB/BLOB 类型转换 2. 图形化监控同步状态 3. 支持断点续传和一致性校验 --- #### 四、性能优化建议(引用[4]) 1. **Flink CBO 调优** 在 `flink-conf.yaml` 中启用成本优化器: ```yaml table.optimizer.cbo.enabled: true table.optimizer.join-reorder-enabled: true ``` 2. **内存配置** 增加 TaskManager 内存防止 OOM: ```yaml taskmanager.memory.process.size: 8192m taskmanager.memory.managed.fraction: 0.4 ``` 3. **并行度调整** 根据大字段分布设置并行度: ```java env.fromSource(oracleSource, WatermarkStrategy.noWatermarks(), "Oracle Source") .setParallelism(4) // 根据字段大小调整 .sinkTo(sink); ``` --- #### 五、验证方法 1. **日志检查** 在 Debezium 日志中搜索 `LOB_ENABLED` 确认配置生效 2. **中间数据验证** 在 Flink 作业中添加 `print()` 观察字段内容: ```java stream.map(row -> "CLOB length: " + row.getString(0).length()).print(); ``` 3. **Doris 数据查验** ```sql SELECT LENGTH(clob_col) AS clob_len, LENGTH(blob_col) AS blob_len FROM doris_table LIMIT 10; ``` > **关键提示**:若 CLOB 超过 64KB,需在 Doris 侧使用 `TEXT` 类型,并在 Flink 中确保 JSON 序列化完整(`sink.properties.format=json`)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值