使用MySQL从Java中的多个表中选择带前缀的列
我必须处理Java来创建一个restful API,我将它与MySQL一起使用来查询数据库 我对Java非常陌生,这可能是一个非常基本的问题,但我习惯于PHP框架,在这些框架中不存在这个问题,我想知道用Java做这件事的方法是什么 我查询了3个通过外键连接它们的表,发现如果其中两个表具有相同的列名,则只返回其中一个。在使用MySQL从Java中的多个表中选择带前缀的列,java,mysql,sql,prepared-statement,executequery,Java,Mysql,Sql,Prepared Statement,Executequery,我必须处理Java来创建一个restful API,我将它与MySQL一起使用来查询数据库 我对Java非常陌生,这可能是一个非常基本的问题,但我习惯于PHP框架,在这些框架中不存在这个问题,我想知道用Java做这件事的方法是什么 我查询了3个通过外键连接它们的表,发现如果其中两个表具有相同的列名,则只返回其中一个。在from语句中声明的最新表中的一个。看来他们被推翻了 例如,如果表type\u应用程序和type\u叶子都有名称列,则此查询中将仅返回type\u叶子中的名称列: select *
from
语句中声明的最新表中的一个。看来他们被推翻了
例如,如果表type\u应用程序
和type\u叶子
都有名称
列,则此查询中将仅返回type\u叶子
中的名称
列:
select * from leaves, type_applications, type_leaves
where leaves.type_leave = type_leaves.id and
leaves.type_application = type_applications.id;
现在,我知道这可以很容易地解决,方法是指定以表名为前缀的所有所需列名(以防重复),并使用as
创建别名:
select leaves.id, type_leaves.name as leaves_name, type_applications.name as application_name
from leaves, type_applications, type_leaves
where leaves.type_leave = type_leaves.id and
leaves.type_application = type_applications.id;
但这听起来并不是我的最佳解决方案。我宁愿继续使用*
来获取所有字段(这是我一直想要的)
这也将有助于生成更小的查询,更易于阅读和维护,以防我随着时间的推移不断添加或删除表中的列
有什么解决办法吗?在Java中如何处理它?由于性能原因,“选择*”在大多数严重情况下都是一种不好的做法,我认为即使在PHP中也是一样的。而且,即使使用“select*”也能正确返回该列,您可以使用result.getMetaData()来检查它
for (int i=1; i<rs.getMetaData().getColumnCount(); i++) {
System.out.println(rs.getMetaData().getColumnName(i));
}
for(int i=1;i“select*”在大多数严重的情况下确实是一种不好的做法,因为性能问题,我认为即使在PHP中也是如此。
而且,即使使用“select*”也能正确返回该列,您可以使用result.getMetaData()来检查它
for (int i=1; i<rs.getMetaData().getColumnCount(); i++) {
System.out.println(rs.getMetaData().getColumnName(i));
}
for(inti=1;i在这种情况下,可能会重命名其中一列
要解决此问题,可以从executeQuery(ResultSet.getMetaData方法)返回的结果集中查询列列表。这将返回
getColumnCount()将返回结果中的列数
getColumnLabel(int列)将返回该列的名称
如果两列具有相同的名称“name”,则这两列的标签可能不同。在这种情况下,可能会重命名其中一列
要解决此问题,可以从executeQuery(ResultSet.getMetaData方法)返回的结果集中查询列列表。这将返回
getColumnCount()将返回结果中的列数
getColumnLabel(int列)将返回该列的名称
如果两列具有相同的名称“name”,则这两列的标签可能不同。您可以编写一个函数,根据表名和列名返回列的索引
public int getIndex(ResultSet rs, String table, String column) throws SQLException
{
for (int i=1; i < rs.getMetaData().getColumnCount(); i++)
{
if (rs.getMetaData().getTableName(i).equals(table) && rs.getMetaData().getColumnName(i).equals(column))
{
return i;
}
}
return -1;
}
您可以编写一个函数,根据表名和列名返回列的索引
public int getIndex(ResultSet rs, String table, String column) throws SQLException
{
for (int i=1; i < rs.getMetaData().getColumnCount(); i++)
{
if (rs.getMetaData().getTableName(i).equals(table) && rs.getMetaData().getColumnName(i).equals(column))
{
return i;
}
}
return -1;
}
我也是Java新手,所以我听到了;).但在我尽力回答您之前,如果您不介意的话,我想说一句话。您的问题与Java和数据库/SQL有关。您提供了一些SQL,其中解释了有关DB表的一些内容以及您可能从查询中获得的内容。但您的主要问题是Java,您没有提供任何Java代码,以便我们能够理解不管你想完成什么,你到底在哪里遇到了问题。尽管如此,我希望以下内容能让你了解你能做些什么:
首先,查询中的ResultSet
包含name
两列。它们不会被覆盖。下面是一个示例:
String sql = "select * from leaves, type_applications, type_leaves " +
"where leaves.type_leave = type_leaves.id and " +
"leaves.type_application = type_applications.id";
ResultSet rs = stmt.executeQuery(sql);
DBTablePrinter.printResultSet(rs);
这将打印如下内容:
Printing 1 rows from table(s) LEAVES, TYPE_APPLICATIONS, TYPE_LEAVES
+----+------------------------+------------+------------------+----+--------+
| ID | SOMETHING_ABOUT_LEAVES | ID | NAME | ID | NAME |
+----+------------------------+----+--------------------+----+--------------+
| 1 | green | 1 | application type 1 | 1 | leave type 1 |
+----+------------------------+----+--------------------+----+--------------+
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// A HashMap with column names as key
Map<String, List<String>> columns = new HashMap<>(columnCount);
// Loop through columns, rename as you wish
for (int i = 1; i <= columnCount; i++) {
if (rsmd.getColumnLabel(i).equals("NAME")) {
if (rsmd.getTableName(i).equals("TYPE_LEAVES")) {
columns.put("L_NAME", new ArrayList<>());
} else {
columns.put("APP_NAME", new ArrayList<>());
}
} else {
columns.put(rsmd.getColumnLabel(i), new ArrayList<>());
}
}
// Iterate over ResultSet rows, add values to columns
while (rs.next()) {
for (int i = 1; i <= columnCount; i++) {
String columnName = rsmd.getColumnLabel(i);
String tableName = rsmd.getTableName(i);
if (columnName.equals("NAME")) {
if (tableName.equals("TYPE_LEAVES")) {
columns.get("L_NAME").add(rs.getString(i));
} else {
columns.get("APP_NAME").add(rs.getString(i));
}
} else {
columns.get(columnName).add(rs.getString(i))
}
}
}
// Print, for example, first row values for L_NAME and APP_NAME columns
System.out.println(columns.get("L_NAME").get(0));
System.out.println(columns.get("APP_NAME").get(0));
// Prints:
// leave type 1
// application type 1
可以看到,两个代码>名称< /COD>列都在那里。(我使用了DabTable打印机实用程序类,我写了。如果您感兴趣的话,您可以找到它。我也建议,正如Strawberry在评论中所做的那样,考虑使用显式连接语法。
我正在使用另一个DB(H2),因此我不确定这是否适用于MySQL,但您可以尝试(它适用于我):
如果这不起作用,或者您真的需要在列名前加前缀,并使用这些新名称访问列名,那么我所能想到的就是这样:
Printing 1 rows from table(s) LEAVES, TYPE_APPLICATIONS, TYPE_LEAVES
+----+------------------------+------------+------------------+----+--------+
| ID | SOMETHING_ABOUT_LEAVES | ID | NAME | ID | NAME |
+----+------------------------+----+--------------------+----+--------------+
| 1 | green | 1 | application type 1 | 1 | leave type 1 |
+----+------------------------+----+--------------------+----+--------------+
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// A HashMap with column names as key
Map<String, List<String>> columns = new HashMap<>(columnCount);
// Loop through columns, rename as you wish
for (int i = 1; i <= columnCount; i++) {
if (rsmd.getColumnLabel(i).equals("NAME")) {
if (rsmd.getTableName(i).equals("TYPE_LEAVES")) {
columns.put("L_NAME", new ArrayList<>());
} else {
columns.put("APP_NAME", new ArrayList<>());
}
} else {
columns.put(rsmd.getColumnLabel(i), new ArrayList<>());
}
}
// Iterate over ResultSet rows, add values to columns
while (rs.next()) {
for (int i = 1; i <= columnCount; i++) {
String columnName = rsmd.getColumnLabel(i);
String tableName = rsmd.getTableName(i);
if (columnName.equals("NAME")) {
if (tableName.equals("TYPE_LEAVES")) {
columns.get("L_NAME").add(rs.getString(i));
} else {
columns.get("APP_NAME").add(rs.getString(i));
}
} else {
columns.get(columnName).add(rs.getString(i))
}
}
}
// Print, for example, first row values for L_NAME and APP_NAME columns
System.out.println(columns.get("L_NAME").get(0));
System.out.println(columns.get("APP_NAME").get(0));
// Prints:
// leave type 1
// application type 1
ResultSetMetaData rsmd=rs.getMetaData();
int columnCount=rsmd.getColumnCount();
//以列名作为键的哈希映射
Map columns=新的HashMap(columnCount);
//循环浏览列,根据需要重命名
对于(inti=1;i我也是Java新手,所以我听到了;).但在我尽力回答您之前,如果您不介意的话,我想说一句话。您的问题与Java和数据库/SQL有关。您提供了一些SQL,其中解释了有关DB表的一些内容以及您可能从查询中获得的内容。但您的主要问题是Java,您没有提供任何Java代码,以便我们能够理解不管你想完成什么,你到底在哪里遇到了问题。尽管如此,我希望以下内容能让你了解你能做些什么:
首先,查询中的ResultSet
包含name
两列。它们不会被覆盖。下面是一个示例:
String sql = "select * from leaves, type_applications, type_leaves " +
"where leaves.type_leave = type_leaves.id and " +
"leaves.type_application = type_applications.id";
ResultSet rs = stmt.executeQuery(sql);
DBTablePrinter.printResultSet(rs);
这将打印如下内容:
Printing 1 rows from table(s) LEAVES, TYPE_APPLICATIONS, TYPE_LEAVES
+----+------------------------+------------+------------------+----+--------+
| ID | SOMETHING_ABOUT_LEAVES | ID | NAME | ID | NAME |
+----+------------------------+----+--------------------+----+--------------+
| 1 | green | 1 | application type 1 | 1 | leave type 1 |
+----+------------------------+----+--------------------+----+--------------+
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// A HashMap with column names as key
Map<String, List<String>> columns = new HashMap<>(columnCount);
// Loop through columns, rename as you wish
for (int i = 1; i <= columnCount; i++) {
if (rsmd.getColumnLabel(i).equals("NAME")) {
if (rsmd.getTableName(i).equals("TYPE_LEAVES")) {
columns.put("L_NAME", new ArrayList<>());
} else {
columns.put("APP_NAME", new ArrayList<>());
}
} else {
columns.put(rsmd.getColumnLabel(i), new ArrayList<>());
}
}
// Iterate over ResultSet rows, add values to columns
while (rs.next()) {
for (int i = 1; i <= columnCount; i++) {
String columnName = rsmd.getColumnLabel(i);
String tableName = rsmd.getTableName(i);
if (columnName.equals("NAME")) {
if (tableName.equals("TYPE_LEAVES")) {
columns.get("L_NAME").add(rs.getString(i));
} else {
columns.get("APP_NAME").add(rs.getString(i));
}
} else {
columns.get(columnName).add(rs.getString(i))
}
}
}
// Print, for example, first row values for L_NAME and APP_NAME columns
System.out.println(columns.get("L_NAME").get(0));
System.out.println(columns.get("APP_NAME").get(0));
// Prints:
// leave type 1
// application type 1
可以看到,两个代码>名称< /COD>列都在那里。(我使用了DabTable打印机实用程序类,我写了。如果您感兴趣的话,您可以找到它。我也建议,正如Strawberry在评论中所做的那样,考虑使用显式连接语法。
我正在使用另一个DB(H2),因此我不确定这是否适用于MySQL,但您可以尝试(它适用于我):
如果这不起作用,或者您真的需要在列名前加前缀,并使用这些新名称访问列名,那么我所能想到的就是这样:
Printing 1 rows from table(s) LEAVES, TYPE_APPLICATIONS, TYPE_LEAVES
+----+------------------------+------------+------------------+----+--------+
| ID | SOMETHING_ABOUT_LEAVES | ID | NAME | ID | NAME |
+----+------------------------+----+--------------------+----+--------------+
| 1 | green | 1 | application type 1 | 1 | leave type 1 |
+----+------------------------+----+--------------------+----+--------------+
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
// A HashMap with column names as key
Map<String, List<String>> columns = new HashMap<>(columnCount);
// Loop through columns, rename as you wish
for (int i = 1; i <= columnCount; i++) {
if (rsmd.getColumnLabel(i).equals("NAME")) {
if (rsmd.getTableName(i).equals("TYPE_LEAVES")) {
columns.put("L_NAME", new ArrayList<>());
} else {
columns.put("APP_NAME", new ArrayList<>());
}
} else {
columns.put(rsmd.getColumnLabel(i), new ArrayList<>());
}
}
// Iterate over ResultSet rows, add values to columns
while (rs.next()) {
for (int i = 1; i <= columnCount; i++) {
String columnName = rsmd.getColumnLabel(i);
String tableName = rsmd.getTableName(i);
if (columnName.equals("NAME")) {
if (tableName.equals("TYPE_LEAVES")) {
columns.get("L_NAME").add(rs.getString(i));
} else {
columns.get("APP_NAME").add(rs.getString(i));
}
} else {
columns.get(columnName).add(rs.getString(i))
}
}
}
// Print, for example, first row values for L_NAME and APP_NAME columns
System.out.println(columns.get("L_NAME").get(0));
System.out.println(columns.get("APP_NAME").get(0));
// Prints:
// leave type 1
// application type 1
结果