Sql 动态构造一个以您选择的别名为前缀的列名字符串。

Sql 动态构造一个以您选择的别名为前缀的列名字符串。,sql,join,Sql,Join,对于使用MySQL C-API的用户,您的问题有一个直接的答案 考虑到SQL: SELECT a.*, b.*, c.* FROM table_a a JOIN table_b b USING (x) JOIN table_c c USING (y) “mysql_stmt_result_metadata()”中的结果将准备好的SQL查询中的字段定义为结构mysql_字段[]。每个字段包含以下数据: char *name; /* Name of colu

对于使用MySQL C-API的用户,您的问题有一个直接的答案

考虑到SQL:

  SELECT a.*, b.*, c.* FROM table_a a JOIN table_b b USING (x) JOIN table_c c USING (y)
“mysql_stmt_result_metadata()”中的结果将准备好的SQL查询中的字段定义为结构mysql_字段[]。每个字段包含以下数据:

  char *name;                 /* Name of column (may be the alias) */
  char *org_name;             /* Original column name, if an alias */
  char *table;                /* Table of column if column was a field */
  char *org_table;            /* Org table name, if table was an alias */
  char *db;                   /* Database for table */
  char *catalog;              /* Catalog for table */
  char *def;                  /* Default value (set by mysql_list_fields) */
  unsigned long length;       /* Width of column (create length) */
  unsigned long max_length;   /* Max width for selected set */
  unsigned int name_length;
  unsigned int org_name_length;
  unsigned int table_length;
  unsigned int org_table_length;
  unsigned int db_length;
  unsigned int catalog_length;
  unsigned int def_length;
  unsigned int flags;         /* Div flags */
  unsigned int decimals;      /* Number of decimals in field */
  unsigned int charsetnr;     /* Character set */
  enum enum_field_types type; /* Type of field. See mysql_com.h for types */
注意以下字段:目录、表、组织名称

现在您知道SQL中的哪些字段属于哪个模式(又称目录)和表。 这就足以从多表sql查询中通用地标识每个字段,而无需任何别名


一个实际的产品SQLYG显示在这样一个manor中使用这个精确的数据,当PK字段存在时,它们能够独立地更新多表联接的每个表。

如果没有别名,就无法做到这一点,因为,您将如何引用where子句中的字段,如果要加入的2个或3个表中存在该字段?
mysql不清楚您要引用哪个表。

我完全理解为什么这是必要的-至少对我来说,在快速原型制作过程中,当有很多表需要连接时,它很方便,包括许多内部连接。只要第二个“joinedtable.*”字段通配符中的列名相同,主表的字段值就会被joinedtable值覆盖。当必须反复手动指定带有别名的表字段时,容易出错、令人沮丧且违反DRY

下面是一个PHP(Wordpress)函数,通过代码生成来实现这一点,并提供了一个如何使用它的示例。在本例中,它用于快速生成自定义查询,该查询将提供通过高级自定义字段引用的相关wordpress帖子的字段


您的问题的答案似乎是否定的,但是您可以使用的一种方法是指定一个虚拟列来分隔每个新表。如果在脚本语言(如Python或PHP)中循环遍历列列表的结果集,这种方法尤其有效

-- Create alias-view for specific table.

create or replace function mkaview(schema varchar, tab varchar, prefix varchar)
    returns table(orig varchar, alias varchar) as $$
declare
    qtab varchar;
    qview varchar;
    qcol varchar;
    qacol varchar;
    v record;
    sql varchar;
    len int;
begin
    qtab := '"' || schema || '"."' || tab || '"';
    qview := '"' || schema || '"."av' || prefix || tab || '"';
    sql := 'create view ' || qview || ' as select';

    for v in select * from information_schema.columns
            where table_schema = schema and table_name = tab
    loop
        qcol := '"' || v.column_name || '"';
        qacol := '"' || prefix || v.column_name || '"';

        sql := sql || ' ' || qcol || ' as ' || qacol;
        sql := sql || ', ';

        return query select qcol::varchar, qacol::varchar;
    end loop;

    len := length(sql);
    sql := left(sql, len - 2); -- trim the trailing ', '.
    sql := sql || ' from ' || qtab;

    raise info 'Execute SQL: %', sql;
    execute sql;
end
$$ language plpgsql;

我知道这并不能准确回答您的问题,但如果您是一名编码人员,这是一种用重复的列名分隔表的好方法。希望这对某人有所帮助。

我完全理解您关于重复字段名的问题

我也需要它,直到我编写了自己的函数来解决它。如果您使用的是PHP,您可以使用它,如果您有以下功能,也可以使用您所使用的语言编写代码

这里的诀窍是
mysql\u field\u table()
返回表名,
mysql\u field\u name()

这是所有列的前缀;)

问候,

-- This will create a view "avp_person" with "p_" prefix to all column names.
select * from mkaview('public', 'person', 'p_');

select * from avp_person;
函数mysql\u行\u和列($query){
$result=mysql\u query($query);
if(!$result)返回false;//mysql\u error()可以在外部使用
$fields=mysql\u num\u字段($result);
$rows=array();
而($row=mysql\u fetch\u row($result)){
$newRow=array();

对于($i=0;$i),这个问题在实践中非常有用。只需列出软件编程中的每个显式列,在这些列中,您需要特别小心地处理所有条件

想象一下,当调试时,或者尝试使用DBMS作为日常办公工具时,我们需要编写大量SQL代码,而不是特定程序员抽象底层基础设施的可变实现。这种情况随处可见,如数据库转换、迁移、管理等。这些SQL中的大多数只执行一次不要忘记,SQL的发明不仅仅是为了程序员使用

通常我会创建一个以列名为前缀的实用程序视图,这里是pl/pgsql中的函数,这并不容易,但您可以将其转换为其他过程语言

DECLARE @asStatements varchar(8000)

SELECT @asStatements = ISNULL(@asStatements + ', ','') + QUOTENAME(table_name) + '.' + QUOTENAME(column_name) + ' AS ' + '[' + table_name + '.' + column_name + ']'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'TABLE_A' OR TABLE_NAME = 'TABLE_B'
ORDER BY ORDINAL_POSITION
示例:

EXEC('SELECT ' + @asStatements + ' FROM TABLE_A a JOIN TABLE_B b USING (some_id)');
从这一点出发,我会这样处理这个问题:

首先创建所有
AS
语句的列表:

SELECT a.*, b.* FROM TABLE_A a JOIN TABLE_B b USING (some_id);
然后在查询中使用它:

const schema = { columns: ['id','another_column','yet_another_column'] }
但是,这可能需要修改,因为类似的东西只在SQL Server中测试过。但这段代码在SQL Server中并不完全有效,因为不支持使用


如果您可以测试/更正MySQL之类的代码,请发表评论。

我通过重命名相关表中的字段解决了类似的问题。是的,我有权这样做,并且理解每个人可能都没有。我为表中表示表名的每个字段添加了前缀。因此,SQL posOP的ted将保持不变-

const prefix = (table, columns) => columns.reduce((previous, column) => {
  previous.push(table + '.' + column + ' AS ' + table + '_' + column);
  return previous;
}, []);

并且仍然给出预期的结果-易于识别输出字段所属的表。

最近在NodeJS和Postgres中遇到了这个问题

ES6方法

据我所知,没有任何RDBMS功能提供此功能,因此我创建了一个包含所有字段的对象,例如:

const columns_joined = [...prefix('tab1',schema.columns), ...prefix('tab2',schema.columns)];
定义了一个减缩器以将字符串与表名连接在一起:

console.log('SELECT ' + columns_joined.join(',') + ' FROM tab1, tab2 WHERE tab1.id = tab2.id');
这将返回一个字符串数组。为每个表调用该数组并合并结果:

select 
    s.*
  , '' as _prefix__creator_
  , u.*
  , '' as _prefix__speaker_
  , p.*
from statements s 
  left join users u on s.creator_user_id = u.user_id
  left join persons p on s.speaker_person_id = p.person_id
输出最终SQL语句:

const PREFIX_INDICATOR = '_prefix__'
const STOP_PREFIX_INDICATOR = '_stop_prefix'

/** Adds a <prefix> to all properties that follow a property with the name: PREFIX_INDICATOR<prefix> */
function addPrefixes(fields, row) {
  let prefix = null
  for (const field of fields) {
    const key = field.name
    if (key.startsWith(PREFIX_INDICATOR)) {
      if (row[key] !== '') {
        throw new Error(`PREFIX_INDICATOR ${PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = key.substr(PREFIX_INDICATOR.length)
      delete row[key]
    } else if (key === STOP_PREFIX_INDICATOR) {
      if (row[key] !== '') {
        throw new Error(`STOP_PREFIX_INDICATOR ${STOP_PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = null
      delete row[key]
    } else if (prefix) {
      const prefixedKey = prefix + key
      row[prefixedKey] = row[key]
      delete row[key]
    }
  }
  return row
}

PHP7.2+MySQL/Mariadb

MySQL将向您发送多个同名字段。即使在终端客户端中也是如此。但如果您需要关联数组,则必须自己制作密钥

感谢@axelbrz提供的原始版本。我已将其移植到较新的php,并对其进行了一些清理:

函数mysqli\u行与列($link,$query){
$result=mysqli\u查询($link,$query);
如果(!$result){
返回mysqli_错误($link);
}
$field\u count=mysqli\u num\u字段($result);
$fields=array();
对于($i=0;$i<$field\u count;$i++){
$field=mysqli\u fetch\u field\u direct($result,$i);
$fields[]=$field->table
EXEC('SELECT ' + @asStatements + ' FROM TABLE_A a JOIN TABLE_B b USING (some_id)');
SELECT a.*, b.* FROM TABLE_A a JOIN TABLE_B b USING (some_id);
const schema = { columns: ['id','another_column','yet_another_column'] }
const prefix = (table, columns) => columns.reduce((previous, column) => {
  previous.push(table + '.' + column + ' AS ' + table + '_' + column);
  return previous;
}, []);
const columns_joined = [...prefix('tab1',schema.columns), ...prefix('tab2',schema.columns)];
console.log('SELECT ' + columns_joined.join(',') + ' FROM tab1, tab2 WHERE tab1.id = tab2.id');
select 
    s.*
  , '' as _prefix__creator_
  , u.*
  , '' as _prefix__speaker_
  , p.*
from statements s 
  left join users u on s.creator_user_id = u.user_id
  left join persons p on s.speaker_person_id = p.person_id
const PREFIX_INDICATOR = '_prefix__'
const STOP_PREFIX_INDICATOR = '_stop_prefix'

/** Adds a <prefix> to all properties that follow a property with the name: PREFIX_INDICATOR<prefix> */
function addPrefixes(fields, row) {
  let prefix = null
  for (const field of fields) {
    const key = field.name
    if (key.startsWith(PREFIX_INDICATOR)) {
      if (row[key] !== '') {
        throw new Error(`PREFIX_INDICATOR ${PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = key.substr(PREFIX_INDICATOR.length)
      delete row[key]
    } else if (key === STOP_PREFIX_INDICATOR) {
      if (row[key] !== '') {
        throw new Error(`STOP_PREFIX_INDICATOR ${STOP_PREFIX_INDICATOR} must not appear with a value, but had value: ${row[key]}`)
      }
      prefix = null
      delete row[key]
    } else if (prefix) {
      const prefixedKey = prefix + key
      row[prefixedKey] = row[key]
      delete row[key]
    }
  }
  return row
}
const {
  addPrefixes,
  PREFIX_INDICATOR,
  STOP_PREFIX_INDICATOR,
} = require('./BaseDao')

describe('addPrefixes', () => {
  test('adds prefixes', () => {
    const fields = [
      {name: 'id'},
      {name: PREFIX_INDICATOR + 'my_prefix_'},
      {name: 'foo'},
      {name: STOP_PREFIX_INDICATOR},
      {name: 'baz'},
    ]
    const row = {
      id: 1,
      [PREFIX_INDICATOR + 'my_prefix_']: '',
      foo: 'bar',
      [STOP_PREFIX_INDICATOR]: '',
      baz: 'spaz'
    }
    const expected = {
      id: 1,
      my_prefix_foo: 'bar',
      baz: 'spaz',
    }
    expect(addPrefixes(fields, row)).toEqual(expected)
  })
})
select row_to_json(tab1.*),tab1_json, row_to_json(tab2.*) tab2_json 
 from tab1
 join tab2 on tab2.t1id=tab1.id
select
    name + ' as prefix.' + name + ','
from sys.columns where object_id = object_id('mytable')
order by column_id