我正在尝试使用select语句从某个MySQL表中获取除一个以外的所有列。有没有简单的方法可以做到这一点?
编辑:此表中有53列(不是我的设计)
我正在尝试使用select语句从某个MySQL表中获取除一个以外的所有列。有没有简单的方法可以做到这一点?
编辑:此表中有53列(不是我的设计)
Answers:
实际上有一种方法,您当然需要具有执行此操作的权限...
SET @sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME), '<columns_to_omit>,', '') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<table>' AND TABLE_SCHEMA = '<database>'), ' FROM <table>');
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;
更换 <table>, <database> and <columns_to_omit>
<column_name>
在mysql定义(手动)中,没有这样的东西。但是,如果您有非常多的列col1
,... col100
,,则可能会有用:
DROP TABLE IF EXISTS temp_tb;
CREATE TEMPORARY TABLE ENGINE=MEMORY temp_tb SELECT * FROM orig_tb;
ALTER TABLE temp_tb DROP col_x;
SELECT * FROM temp_tb;
DROP TABLE IF EXISTS temp_tb;
你可以做:
SELECT column1, column2, column4 FROM table WHERE whatever
没有获得column3,尽管也许您正在寻找更通用的解决方案?
如果您想排除某个字段的值(例如出于安全考虑/敏感信息),则可以将该列检索为null。
例如
SELECT *, NULL AS salary FROM users
salary
列。但是,由于它是在*之后检索的,因此它将覆盖原始文件。它虽然不漂亮,但确实有效。
据我所知,没有。您可以执行以下操作:
SELECT col1, col2, col3, col4 FROM tbl
并手动选择所需的列。但是,如果您需要很多列,则可能只需要执行以下操作:
SELECT * FROM tbl
只是忽略你不想要的
对于您的特殊情况,我建议:
SELECT * FROM tbl
除非您只需要几列。如果只需要四列,则:
SELECT col3, col6, col45, col 52 FROM tbl
会很好,但是如果您想要50列,那么构成查询的任何代码都将变得(太难理解)。
在尝试@Mahomedalid和@Junaid的解决方案时,我发现了一个问题。因此想共享它。如果列名包含空格或连字符(例如,签入),则查询将失败。一种简单的解决方法是在列名前后使用反引号。修改后的查询如下
SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(CONCAT("`", COLUMN_NAME, "`")) FROM
INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;
如果您不想选择的列中包含大量数据,并且由于速度问题而不想包含它,并且您经常选择其他列,则建议您创建一个新表使用您通常不会用原始表的键选择的一个字段,然后从原始表中删除该字段。当实际需要该额外字段时,请加入表。
您可以使用DESCRIBE my_table并使用其结果动态生成SELECT语句。
我的主要问题是加入表时获得的许多列。尽管这不是您的问题(如何从一个表中选择所有列,而是选择所有列)的答案,但我认为值得一提的是,您可以指定从特定表中获取所有列,而不仅仅是指定。table.
这是一个如何可能非常有用的示例:
选择用户。*,phone.meta_value作为电话,zipcode.meta_value作为邮政编码 来自用户 左加入user_meta作为电话 on((users.user_id = phone.user_id)AND(phone.meta_key ='phone')) 左加入user_meta作为邮政编码 on((users.user_id = zipcode.user_id)AND(zipcode.meta_key ='zipcode')))
结果是用户表中的所有列,以及从元表中联接的另外两个列。
@Mahomedalid
除了来自的评论中告知的这一事实之外,我还喜欢答案@Bill Karwin
。@Jan Koritak
我所面对的问题确实是我所面对的,但是我已经找到了解决的办法,只想在这里与面临此问题的任何人分享。
我们可以使用Prepared语句的子查询中的where子句替换REPLACE函数,如下所示:
使用我的表名和列名
SET @SQL = CONCAT('SELECT ', (SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' AND COLUMN_NAME NOT IN ('id')), ' FROM users');
PREPARE stmt1 FROM @SQL;
EXECUTE stmt1;
因此,这将仅排除该字段id
,而不排除company_id
即使您查询所有列,也要指定要查询的列是一个好习惯。
因此,我建议您在语句中写出每一列的名称(不包括不需要的列)。
SELECT
col1
, col2
, col3
, col..
, col53
FROM table
做就是了
SELECT * FROM table WHERE whatever
然后将该列放入您喜欢的编程语言中:php
while (($data = mysql_fetch_array($result, MYSQL_ASSOC)) !== FALSE) {
unset($data["id"]);
foreach ($data as $k => $v) {
echo"$v,";
}
}
我同意列出所有列的“简单”解决方案,但这可能很麻烦,而且错别字会浪费很多时间。我使用函数“ getTableColumns”来检索适合粘贴到查询中的列的名称。然后,我要做的就是删除不需要的内容。
CREATE FUNCTION `getTableColumns`(tablename varchar(100))
RETURNS varchar(5000) CHARSET latin1
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE res VARCHAR(5000) DEFAULT "";
DECLARE col VARCHAR(200);
DECLARE cur1 CURSOR FOR
select COLUMN_NAME from information_schema.columns
where TABLE_NAME=@table AND TABLE_SCHEMA="yourdatabase" ORDER BY ORDINAL_POSITION;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur1;
REPEAT
FETCH cur1 INTO col;
IF NOT done THEN
set res = CONCAT(res,IF(LENGTH(res)>0,",",""),col);
END IF;
UNTIL done END REPEAT;
CLOSE cur1;
RETURN res;
您的结果返回一个逗号分隔的字符串,例如...
col1,col2,col3,col4,... col53
我也想要这个,所以我创建了一个函数。
public function getColsExcept($table,$remove){
$res =mysql_query("SHOW COLUMNS FROM $table");
while($arr = mysql_fetch_assoc($res)){
$cols[] = $arr['Field'];
}
if(is_array($remove)){
$newCols = array_diff($cols,$remove);
return "`".implode("`,`",$newCols)."`";
}else{
$length = count($cols);
for($i=0;$i<$length;$i++){
if($cols[$i] == $remove)
unset($cols[$i]);
}
return "`".implode("`,`",$cols)."`";
}
}
因此,它的工作方式是先输入表,然后输入不需要的列或数组中的列:array(“ id”,“ name”,“ whatevercolumn”)
因此,在选择中,您可以像这样使用它:
mysql_query("SELECT ".$db->getColsExcept('table',array('id','bigtextcolumn'))." FROM table");
要么
mysql_query("SELECT ".$db->getColsExcept('table','bigtextcolumn')." FROM table");
Mahomedalid发布的答案有一个小问题:
内部替换功能代码正在替换“<columns_to_delete>,
” ”,如果要替换的字段是concat字符串中的最后一个字段,则替换存在问题,因为最后一个字段没有字符逗号“,”并且未从中删除字符串。
我的建议:
SET @sql = CONCAT('SELECT ', (SELECT REPLACE(GROUP_CONCAT(COLUMN_NAME),
'<columns_to_delete>', '\'FIELD_REMOVED\'')
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = '<table>'
AND TABLE_SCHEMA = '<database>'), ' FROM <table>');
更换<table>
,<database>
和`
在我的情况下,删除的列将替换为字符串“ FIELD_REMOVED”,因为我正尝试保护内存,所以这行得通。(我删除的字段的BLOB约为1MB)
基于@Mahomedalid的答案,我做了一些改进以支持“选择除mysql中的某些以外的所有列”
SET @database = 'database_name';
SET @tablename = 'table_name';
SET @cols2delete = 'col1,col2,col3';
SET @sql = CONCAT(
'SELECT ',
(
SELECT GROUP_CONCAT( IF(FIND_IN_SET(COLUMN_NAME, @cols2delete), NULL, COLUMN_NAME ) )
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tablename AND TABLE_SCHEMA = @database
),
' FROM ',
@tablename);
SELECT @sql;
如果确实有很多cols,请使用此sql更改group_concat_max_len
SET @@group_concat_max_len = 2048;
可能是我对扬·科里塔克(Jan Koritak)指出的差异的解决方案
SELECT CONCAT('SELECT ',
( SELECT GROUP_CONCAT(t.col)
FROM
(
SELECT CASE
WHEN COLUMN_NAME = 'eid' THEN NULL
ELSE COLUMN_NAME
END AS col
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
) t
WHERE t.col IS NOT NULL) ,
' FROM employee' );
表:
SELECT table_name,column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'employee' AND TABLE_SCHEMA = 'test'
===============================
table_name column_name
employee eid
employee name_eid
employee sal
===============================
查询结果:
'SELECT name_eid,sal FROM employee'
如果愿意,可以使用SQL生成SQL并评估它生成的SQL。这是一个通用解决方案,因为它从信息模式中提取列名。这是Unix命令行的示例。
替代
echo $(echo 'select concat("select ", group_concat(column_name) , " from TABLE") from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1) | MYSQL
您实际上只需要以这种方式提取一次列名即可构造排除该列的列列表,然后仅使用您已构建的查询。
所以像:
column_list=$(echo 'select group_concat(column_name) from information_schema.columns where table_name="TABLE" and column_name != "EXCLUDEDFIELD" group by "t"' | MYSQL | tail -n 1)
现在,您可以$column_list
在构造的查询中重用该字符串。
我想添加另一种观点来解决此问题,特别是如果要删除的列数较少时。
您可以使用MySQL Workbench之类的数据库工具来为您生成select语句,因此您只需手动删除生成的语句的那些列,然后将其复制到SQL脚本中即可。
在MySQL Workbench中,生成它的方式是:
右键单击表->发送到Sql编辑器->选择所有语句。
公认的答案有几个缺点。
所有这些问题都可以通过简单地包括在反引号来克服SEPARATOR
你GROUP_CONCAT
和使用WHERE
条件,而不是REPLACE()
。出于我的目的(我想还有很多其他人),我希望返回的列名与其在表本身中出现的顺序相同。为此,我们ORDER BY
在GROUP_CONCAT()
函数内部使用一个显式子句:
SELECT CONCAT(
'SELECT `',
GROUP_CONCAT(COLUMN_NAME ORDER BY `ORDINAL_POSITION` SEPARATOR '`,`'),
'` FROM `',
`TABLE_SCHEMA`,
'`.`',
TABLE_NAME,
'`;'
)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE `TABLE_SCHEMA` = 'my_database'
AND `TABLE_NAME` = 'my_table'
AND `COLUMN_NAME` != 'column_to_omit';
我很迟才想出一个答案,坦白地说,这是我一直以来的做法,坦率地说,它比最佳答案要好和整洁100倍,我只希望有人能看到它。并发现它有用
//create an array, we will call it here.
$here = array();
//create an SQL query in order to get all of the column names
$SQL = "SHOW COLUMNS FROM Table";
//put all of the column names in the array
foreach($conn->query($SQL) as $row) {
$here[] = $row[0];
}
//now search through the array containing the column names for the name of the column, in this case i used the common ID field as an example
$key = array_search('ID', $here);
//now delete the entry
unset($here[$key]);
SELECT
语句-这个词甚至不会出现一次。
选择*是SQL反模式。由于许多原因,不应在生产代码中使用它:
处理需要一点时间。当事情运行数百万次时,这些微小的问题就很重要。缓慢的数据库(其中缓慢是由这种类型的草率编码导致的)是最难调整的性能。
这意味着您发送的数据可能会超出所需,这会导致服务器和网络瓶颈。如果您有内部联接,则发送超出您所需数据的机会为100%。
这会引起维护问题,尤其是当您添加了新的列,而您不想在任何地方都看到它们时。此外,如果您有新的列,则可能需要对界面进行某些操作,以确定如何处理该列。
它可以破坏视图(我知道这在SQl服务器中是正确的,在mysql中可能是正确的,也可能不是)。
如果某人足够愚蠢地以不同的顺序重建带有列的表(您不应该这样做,但是会一直发生),那么各种代码都可能会中断。例如,特别是针对插入代码,例如,突然由于您未指定城市而将城市放入address_3字段中时,数据库只能按列顺序进行。当数据类型改变时,这已经足够糟糕了,但是当交换列具有相同的数据类型时,这变得更糟了,因为您有时可能会插入一些混乱的数据来清理。您需要关心数据完整性。
如果在插入中使用它,则在一个表中而不是另一个表中添加新列时,它将中断插入。
它可能会破坏触发器。触发问题可能很难诊断。
将所有这些与添加列名所需的时间相加(哎呀,您甚至可能具有允许您在列名上拖动的界面(我知道我在SQL Server中这样做,我敢打赌有某种方法可以做这个是您用来编写mysql查询的工具。)让我们看看,“我会导致维护问题,会导致性能问题,并且会导致数据完整性问题,但是嘿,我节省了五分钟的开发时间。”在您想要的特定列中。
我还建议您阅读这本书:http ://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers-ebook/dp/B00A376BB2/ref=sr_1_1?s=digital-text& ie= UTF8& qid= 1389896688& sr=1- 1&keywords = sql + antipatterns