我想在具有动态列的表中添加值。 我设法创建了一个包含动态列的表,但我无法弄清楚如何插入数据。
//Create Table
sql = "CREATE TABLE MyDB.myTable" +
"(level INTEGER(255) )";
int columnNumber = 5; //Number of columns
//Add columns
for (i=0;i<columnNumber;i++){
String columnName = "Level_" +i:
String sql = "ALTER TABLE MyDB.myTable ADD " + columnName + " INTEGER(30)";
}
//Insert Data
//How to insert data dynamically, without knowing the number of columns?
答案 0 :(得分:2)
您还可以使用数据库元数据来获取列名称。这样做的好处是,您甚至不需要知道列名,而是在代码中动态检索它们。
public static List<String> getColumns(String tableName, String schemaName) throws SQLException{
ResultSet rs=null;
ResultSetMetaData rsmd=null;
PreparedStatement stmt=null;
List<String> columnNames =null;
String qualifiedName = (schemaName!=null&&!schemaName.isEmpty())?(schemaName+"."+tableName):tableName;
try{
stmt=conn.prepareStatement("select * from "+qualifiedName+" where 0=1");
rs=stmt.executeQuery();//you'll get an empty ResultSet but you'll still get the metadata
rsmd=rs.getMetaData();
columnNames = new ArrayList<String>();
for(int i=1;i<=rsmd.getColumnCount();i++)
columnNames.add(rsmd.getColumnLabel(i));
}catch(SQLException e){
throw e;//or log it
}
finally{
if(rs!=null)
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
throw e
}
if(stmt!=null)
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
throw e
}
}
return columnNames;
}
获得列名后,您可以像往常一样使用它(List.size()当然会给出列数。)
更新:
//I will assume that your values (data to be inserted) is a List of Object types and that it is already populated
List<Object> data = new ArrayList<>();
//you will populate this list
//getting the column names
List<String> columnNames = getColumns("MyTable", "MyDB");
String insertColumns = "";
String insertValues = "";
if(columnNames != null && columnNames.size() > 0){
insertColumns += columnNames.get(0);
insertValues += "?";
}
for(int i = 1; i < columnNames.size();i++){
insertColumns += ", " + columnNames.get(i) ;
insertValues += "?";
}
String insertSql = "INSERT INTO MyDB.MyTable (" + insertColumns + ") values(" + insertValues + ")";
try{
PrepareStatement ps = conn.prepareStatement(insertSql);
for(Object o : data){
ps.setObject(o); //you must pass objects of correct type
}
ps.execute(); //this inserts your data
}catch(SQLException sqle){
//do something with it
}
此代码假定您将正确类型的对象传递给PreparedStatement.setObject(Object o)方法。也可以使用元数据库信息检索列类型,然后使用该信息强制执行类型检查,但这会使代码更加复杂
答案 1 :(得分:0)
如果您知道要插入的列数,则可以使插入查询与创建CREATE TABLE的方式相同。明确命名要添加数据的列,并确保允许留空的列为空(NULL或默认= 0)
INSERT INTO MyDB.myTable (Level_1, Level_2, ...) VALUES (Val_1, Val_2, ...);
另一种方法是将每个插入的值存储在一个单独的行中。这样,您就不会改变表格中的列数。
您需要一个表格,其中包含每组值的ID: - ID - 等级 - 价值
您可以在一个单独的表中注册每个ID: - ID(bigInt,自动增量,主键) - 信息字段 - 时间戳
现在,对于要插入的每组数据,首次插入需要唯一ID。如果您使用第二个表,插入新行将为您提供一个新ID:
INSERT INTO register_table (ID, info, timestamp) VALUES (NULL, 'some info', NOW());
这将为您提供一个新ID(last_inserted_id)。 现在使用此ID将所有值插入另一个表中:
for(i=0i<columnNumber;i++){
"INSERT INTO _table (ID, Level, _Value) VALUES ("+ the_ID +", "+ i +", "+ the_VALUE +");";
}
如果你想获取数据:
"SELECT Level, _Value FROM _table WHERE ID="+ the_ID +" ORDER BY Level;";