如何修改Databricks数据表列类型?解决ALTER TABLE变更报错问题
问题:Databricks中CSV读取为字符串列后无法通过ALTER TABLE修改类型
我将Blob存储中的CSV文件在Databricks中读取为DataFrame,执行代码如下:
sourcefile = 'MiningProcess_Flotation_Plant_Database.csv' df = spark.read.format('csv').option("header","true").load(db_ws.dp_engagement + '/' + sourcefile) display(df)
随后将其保存为永久表:
df.write.format("parquet").saveAsTable("MY_PERMANENT_TABLE_NAME")
操作成功,但所有数值列均被创建为字符串类型。尝试通过SQL修改列类型:
ALTER TABLE MY_PERMANENT_TABLE_NAME CHANGE `% Iron Concentrate` TYPE decimal
收到报错:
Error in SQL statement: AnalysisException: ALTER TABLE CHANGE COLUMN is not supported for changing column '% Iron Concentrate' with type 'StringType' to '% Iron Concentrate' with type 'DecimalType(10,0)'
解决方案
1. 读取CSV时自动推断数据类型
Spark默认不会自动识别CSV的数值类型,添加inferSchema="true"参数即可让Spark自动推断列类型,从根源避免类型问题:
sourcefile = 'MiningProcess_Flotation_Plant_Database.csv' df = spark.read.format('csv')\ .option("header", "true")\ .option("inferSchema", "true")\ .load(db_ws.dp_engagement + '/' + sourcefile) display(df) # 重新保存为永久表 df.write.format("parquet").saveAsTable("MY_PERMANENT_TABLE_NAME")
2. 手动指定Schema读取(更精准)
如果自动推断的类型不符合需求(比如需要特定精度的Decimal),可以手动定义Schema:
from pyspark.sql.types import StructType, StructField, StringType, DoubleType, DecimalType # 根据数据集实际列定义Schema,示例仅展示部分列 schema = StructType([ StructField("date", StringType(), nullable=True), StructField("% Iron Feed", DoubleType(), nullable=True), StructField("% Silica Feed", DoubleType(), nullable=True), StructField("% Iron Concentrate", DecimalType(10, 2), nullable=True), # 其余列按实际情况补充... ]) sourcefile = 'MiningProcess_Flotation_Plant_Database.csv' df = spark.read.format('csv')\ .option("header", "true")\ .schema(schema)\ .load(db_ws.dp_engagement + '/' + sourcefile) display(df) df.write.format("parquet").saveAsTable("MY_PERMANENT_TABLE_NAME")
3. 转换现有表的列类型
由于Databricks不支持直接通过ALTER TABLE修改列的基础类型(如String转Decimal),需要通过转换后重新生成表:
方法1:用SQL实现
-- 创建转换后的新表 CREATE TABLE MY_PERMANENT_TABLE_NAME_TRANSFORMED USING parquet AS SELECT date, CAST(`% Iron Feed` AS DOUBLE) AS `% Iron Feed`, CAST(`% Silica Feed` AS DOUBLE) AS `% Silica Feed`, CAST(`% Iron Concentrate` AS DECIMAL(10,2)) AS `% Iron Concentrate`, -- 其他列依次转换... FROM MY_PERMANENT_TABLE_NAME; -- 替换原表(可选操作) DROP TABLE IF EXISTS MY_PERMANENT_TABLE_NAME; ALTER TABLE MY_PERMANENT_TABLE_NAME_TRANSFORMED RENAME TO MY_PERMANENT_TABLE_NAME;
方法2:用PySpark代码实现
from pyspark.sql.functions import col # 读取现有表 df = spark.table("MY_PERMANENT_TABLE_NAME") # 逐个转换列类型 df_transformed = df\ .withColumn("% Iron Feed", col("% Iron Feed").cast("double"))\ .withColumn("% Silica Feed", col("% Silica Feed").cast("double"))\ .withColumn("% Iron Concentrate", col("% Iron Concentrate").cast("decimal(10,2)")) # 其余列按需求转换... # 覆盖原表(注意:此操作会删除原表数据,谨慎执行) df_transformed.write.format("parquet").mode("overwrite").saveAsTable("MY_PERMANENT_TABLE_NAME")
内容的提问来源于stack exchange,提问作者Luis Valencia
相关产品推荐
相关产品推荐

