3

我有一个存储公司员工完整详细信息的数据库。我需要从数据库中的多个表中选择列名,这些表在执行时将为我提供列出特定详细信息所需的列。所以,我尝试了以下查询,它只返回指定表的列。

SELECT TABLE_NAME,COLUMN_NAME
FROM mydatabase.INFORMATION_SCHEMA.COLUMNS Where TABLE_NAME=N'TBLemppersonaldetails'

所有表都有一个名为“EmployeeId”的列,可以被视为主键。现在,我如何通过避免在所有表中重复的某些列(例如更新日期、模式)从所有表中获取所有必需的列。我更喜欢使用“内部连接”来连接所有表格。例如考虑下表:

          Table1                                            Table2
EmployeeId     Name     Address     Mode      EmployeeId   Gender   BloodGroup     Mode
----------------------------------------     -------------------------------------------
   001         abc      No.9,vv      1          001         Male       O+ve          1
                        street,

考虑到上面的示例,我要求在执行查询后列出 EmployeeId、Name、Address、Gender、BloodGroup 列,同时从两个表中排除名为“Mode”的列。我要求您考虑另一种情况,即“EmployeeId”列不存在所谓的“PrimaryKey”约束。PS:我使用的是 SQL Server 2008

4

3 回答 3

1

试试这个——

DDL:

SET NOCOUNT ON;

IF OBJECT_ID (N'dbo.Table1') IS NOT NULL 
    DROP TABLE dbo.Table1 

CREATE TABLE dbo.Table1 
(
      EmployeeId INT
    , Name VARCHAR(30)
    , [Address] VARCHAR(150)
    , Mode INT
    , Img IMAGE
    , UpdateDate DATETIME
    , IpAddress VARCHAR(20)
) 

IF OBJECT_ID (N'dbo.Table2') IS NOT NULL
    DROP TABLE dbo.Table2

CREATE TABLE dbo.Table2 
(
      EmployeeId INT
    , Gender VARCHAR(6)
    , BloodGroup VARCHAR(20)
    , Mode INT
)

INSERT INTO dbo.Table1 (EmployeeId, Name, [Address], Mode, UpdateDate, IpAddress) 
VALUES ('001', 'abc', 'No.9,vv street', 1,'06/04/2013 12:00:00','192.168.0.1')

INSERT INTO dbo.Table2 (EmployeeId, Gender, BloodGroup, Mode)
VALUES ('001', 'Male', 'O+ve', 1) 

询问:

DECLARE @SQL NVARCHAR(MAX)

;WITH cte AS 
(
    SELECT 
          column_name = '[' + c.name + ']'
        , table_name = '[' + s.name + '].[' + o.name + ']'
        , [type_name] = t.name
    FROM sys.columns c WITH (NOLOCK)
    JOIN sys.objects o WITH (NOLOCK) ON c.[object_id] = o.[object_id]
    JOIN sys.schemas s WITH (NOLOCK) ON o.[schema_id] = s.[schema_id]
    JOIN sys.types t WITH (NOLOCK) ON c.user_type_id = t.user_type_id
    WHERE o.name IN ('Table1', 'Table2')
        AND s.name = 'dbo'
        AND o.[type] = 'U'
        AND c.name NOT IN ('Mode', 'UpdateDate', 'IpAddress')  
), unicol AS (
    SELECT TOP 1 column_name 
    FROM cte 
    GROUP BY cte.column_name
    HAVING COUNT(cte.column_name) > 1
), cols AS 
(
    SELECT DISTINCT column_name, [type_name] 
    FROM cte    
), tbl AS 
(
    SELECT DISTINCT table_name
    FROM cte
), rs AS 
(
    SELECT 
          tbl.table_name
        , column_name = ISNULL(cte.column_name, cols.column_name + ' = NULL')
    FROM cols
    CROSS JOIN tbl
    LEFT JOIN cte ON cols.column_name = cte.column_name AND cte.table_name = tbl.table_name
), rs2 AS (
    SELECT uni = ' UNION ALL' + CHAR(13) + 'SELECT ' + STUFF((
        SELECT ', ' + rs.column_name
        FROM rs
        WHERE tbl.table_name = rs.table_name
        GROUP BY rs.column_name
        ORDER BY rs.column_name
        FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + 
        ' FROM ' + table_name
    FROM tbl
) 
SELECT @SQL = 'SELECT 
' + STUFF((
    SELECT CHAR(13) + ', ' + ISNULL(unicol.column_name, cols.column_name + ' = MAX(' 
    + CASE 
        WHEN [type_name] = 'image' THEN 'CONVERT(VARBINARY(MAX), ' + cols.column_name + ')' 
        WHEN [type_name] = 'bit' THEN 'CAST(' + cols.column_name + ' AS CHAR(1))' 
        ELSE cols.column_name 
        END + ')')
    FROM cols
    LEFT JOIN unicol ON cols.column_name = unicol.column_name
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, ' ')
    + ' 
FROM 
(' + STUFF((
    SELECT CHAR(10) + uni
    FROM rs2
    FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 11, '') + CHAR(13) + 
    ') t 
GROUP BY ' + (SELECT column_name FROM unicol)

PRINT @SQL

EXECUTE sys.sp_executesql @SQL

输出:

Address            BloodGroup   EmployeeId  Gender Img      Name
------------------ ------------ ----------- ------ -------- -------
No.9,vv street     O+ve         1           Male   NULL     abc
于 2013-06-03T06:23:15.563 回答
1

您需要动态创建一条 SQL 语句,然后运行该命令

更新 22.06.2013

IF OBJECT_ID('dbo.Table1') IS NOT NULL DROP TABLE dbo.Table1
CREATE TABLE dbo.Table1
 (
  EmployeeId int PRIMARY KEY,
  Name varchar(100),
  Address varchar(100),
  Mode int
  )

INSERT dbo.Table1
VALUES(1, 'abc', 'Address', 1)  

IF OBJECT_ID('dbo.Table2') IS NOT NULL DROP TABLE dbo.Table2
CREATE TABLE dbo.Table2
 ( 
  EmployeeId int PRIMARY KEY,
  Gender varchar(100),
  BloodGroup varchar(100),
  Mode int
  )  

INSERT dbo.Table2
VALUES(1, 'Male', 'O+ve', 1)

DECLARE @TablesWithAlias TABLE([schema] varchar(10), name varchar(20), alias varchar(10))
INSERT @TablesWithAlias
VALUES('dbo', 'Table1', 't1.'),
      ('dbo', 'Table2', 't2.')
DECLARE @dsql nvarchar(max)   
SELECT @dsql = COALESCE(@dsql + ',', '') + MIN(twa.alias) + CASE WHEN o.IsPrimaryKey IS NOT NULL THEN c.name ELSE c.name END
FROM sys.schemas s
  JOIN sys.tables t ON s.schema_id = t.schema_id
  JOIN sys.columns c ON t.object_id = c.object_id
  OUTER APPLY (
               SELECT CASE WHEN OBJECTPROPERTY(object_id(constraint_name), 'IsPrimaryKey') = 1 THEN 1 END AS IsPrimaryKey
               FROM information_schema.key_column_usage k
               WHERE s.name = k.table_schema AND t.name = k.table_name
                 AND c.name = k.COLUMN_NAME
               ) o

  JOIN @TablesWithAlias twa ON s.name = twa.[schema] AND t.name = twa.name               
GROUP BY c.column_id, c.name, o.IsPrimaryKey
HAVING COUNT(*) = 1 OR o.IsPrimaryKey IS NOT NULL
ORDER BY c.column_id
PRINT @dsql

--Your 'Inner Join' to join all the tables.    
SET @dsql = 
  'SELECT ' + @dsql +
  ' FROM dbo.Table1 t1 JOIN dbo.Table2 t2 ON t1.EmployeeId = t2.EmployeeId '
PRINT @dsql
EXEC sp_executesql @dsql
于 2013-06-03T07:42:30.597 回答
0

使用此搜索您的列名:

 SELECT OBJECT_NAME (object_id ),*
 FROM sys.columns
 WHERE name LIKE 'ColumnName'
于 2013-06-03T06:19:19.523 回答