【问题标题】:Retrieve particular value from multiple tables从多个表中检索特定值
【发布时间】:2017-12-16 22:51:27
【问题描述】:

我有 14 张不同类型的员工表。我有一个连接到我的 SQL Server 数据库的 C# 应用程序,当我在文本框中输入姓氏时,它会带回具有该姓氏的记录并将其显示在列表框中。

但是我只用一张桌子就做到了。因此,如果我输入“Jones”,它会从一张表中返回并显示 Jones。

我想把所有 14 张桌子中的所有琼斯带回来。换句话说,当我输入姓氏时,我需要应用程序向我显示所有 14 个表中该姓氏的所有记录。

对此有什么合理的方法?如果我有一张桌子和所有员工在一起,那会容易得多,但我需要分开。基本上,当我单击搜索按钮时,我需要应用程序从具有给定名称的 14 个表中的任何一个中获取。

什么是合适的方法?

【问题讨论】:

  • 为什么需要分离?您可以创建一个合并 14 个表的视图,但拥有一个表可能会更好地提高性能。
  • 嗯,我想把员工分成几类,因为我不知道我以后要如何扩展应用程序。我喜欢销售、技术部门、经理等的想法,而不是将所有类别和所有员工归为一个类别。我明白你在说什么,但我确实需要为所有这些人建立共同点。
  • @NikosKap 为什么不为每个用户分配类别而不是为每个类别创建表?
  • 有可能。
  • @Neir0 这个,其实是一个很有用的建议。我正在认真考虑重构。

标签: c# visual-studio-2017 sql-server-2017


【解决方案1】:

在您的数据库中定义以下存储过程:

CREATE PROCEDURE GetAll_SP
(
    @FirstName VARCHAR(50)
)  
AS
    BEGIN
        (SELECT 1, first_name, last_name FROM UsersTable1 WHERE first_name = @FirstName)
        UNION
        (SELECT 2, first_name, last_name FROM UsersTable2 WHERE first_name = @FirstName)
        UNION
        (SELECT 3, first_name, last_name FROM UsersTable3 WHERE first_name = @FirstName)
        -- ....
    END

GO

或以下替代您不需要对您的用户位置进行任何形式的控制:

CREATE PROCEDURE GetAll_SP
(
    @FirstName VARCHAR(50)
)  
AS
    BEGIN
        (SELECT first_name, last_name FROM UsersTable1 WHERE first_name = @FirstName)
        UNION ALL
        (SELECT first_name, last_name FROM UsersTable2 WHERE first_name = @FirstName)
        UNION ALL
        (SELECT first_name, last_name FROM UsersTable3 WHERE first_name = @FirstName)
        -- ....
    END

GO

然后,在您的代码中:

String firstName = "Jones";

using (SqlCommand cmd = new SqlCommand("GetAll_SP", m_Connection))
{
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add("@FirstName", SqlDbType.VarChar).Value = firstName;

    m_Connection.Open();
    cmd.ExecuteNonQuery();
}

【讨论】:

  • 看起来不错。我会试试这个,然后再检查。不过,我必须在我的 C# 中进行一些更改,因为我使用的是 Lists 和 Dapper,所以应该很有趣。我会回来看看谢谢。
【解决方案2】:

您应该重复您的代码 14 次以从所有这些表中收集值,或者您一次提交所有 14 个表的 SQL 查询,并在一个语句中使用联合或 14 个查询 - 取决于您的数据访问技术...

【讨论】:

  • 我可以添加一个有 14 次查找的存储过程,然后在应用程序中调用该存储过程吗?这有意义吗?
  • 好的,我会试试看,然后回来查看。
  • 这基本上是我需要的,但我需要从 14 个表中提取。不知道这对你们有没有帮助。
【解决方案3】:

好的,要从所有 14 个表中获取结果,您可以使用 UNION ALL 运算符,因此您的 SQL 将类似于:

(SELECT first_name, last_name FROM table1 WHERE first_name='John')
 UNION ALL
(SELECT first_name, last_name FROM table2 WHERE first_name='John')
...
(SELECT first_name, last_name FROM table14 WHERE first_name='John')

您需要在每个选择中拥有相同数量的字段。但是,如果您将所有名称(和任何其他共享数据)保存在一个表中,并使用 Key 与所有具有不同数据集的所有 14 个表连接,则更好的方法是。这样你就可以防止像上面这样的长查询(并且可能是慢查询)并且查询看起来更像这样:

SELECT first_name, last_name, user_type, user_id  WHERE first_name='John'

然后您可以从相应表中检索字段,因为字段 user_type 为您提供信息,在 14 个表中搜索其他数据,而 user_id 为您提供该用户的数据,因此第二个查询看起来像这样:

SELECT job_position, worksheet, other_data FROM tableN WHERE user_id=...

【讨论】:

    【解决方案4】:

    只需设置@SearchStr,每个表中的每一列都会被搜索。

    drop table #results
    go
    
    declare @SearchStr nvarchar(100)
    set @SearchStr = 'Donna%' -- use wildcards
    
    CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
    
    SET NOCOUNT ON
    
    DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
    SET  @TableName = ''
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
    
    WHILE @TableName IS NOT NULL
    BEGIN
        SET @ColumnName = ''
        SET @TableName = 
        (
            SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
            FROM    INFORMATION_SCHEMA.TABLES
            WHERE       TABLE_TYPE = 'BASE TABLE'
                AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
                AND OBJECTPROPERTY(
                        OBJECT_ID(
                            QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                             ), 'IsMSShipped'
                               ) = 0
        )
    
        WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
        BEGIN
            SET @ColumnName =
            (
                SELECT MIN(QUOTENAME(COLUMN_NAME))
                FROM    INFORMATION_SCHEMA.COLUMNS
                WHERE       TABLE_SCHEMA    = PARSENAME(@TableName, 2)
                    AND TABLE_NAME  = PARSENAME(@TableName, 1)
                    AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'text')
                    AND QUOTENAME(COLUMN_NAME) > @ColumnName
            )
    
        print cast(@TableName as nvarchar(200)) + ' ' + @ColumnName
    
        IF @ColumnName IS NOT NULL
            BEGIN
                INSERT INTO #Results
                EXEC
                (
                    --'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
                    --FROM ' + @TableName + ' (NOLOCK) ' +
                    --' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
    
                    'SELECT ''' + @TableName + '.' + @ColumnName + ''', ' + @ColumnName + ' 
                    FROM ' + @TableName + ' (NOLOCK) ' +
                    ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
                )
            END
        END 
    END
    
    SELECT ColumnName, ColumnValue FROM #Results
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-05-25
      • 2020-10-12
      • 1970-01-01
      • 1970-01-01
      • 2021-03-22
      • 2016-01-31
      • 2018-05-26
      • 1970-01-01
      相关资源
      最近更新 更多