2015-06-02 6 views
1

Я пытаюсь создать инструкцию SQL, которая динамически получает имена столбцов из базы данных на основе фильтра. У нас есть таблица с примерно 50 столбцами с префиксом на каждом столбце, чтобы обозначить, к какому «установленному» он относится. Я создал запрос, который отлично работает в SQL Management Studio, но поскольку я хотел бы использовать результаты в приложении .Net, а также в веб-приложении, было бы здорово иметь хранимую процедуру или что-то подобное, что я могу назвать для результатов. Я знаю, что могу вручную указать столбцы в моем запросе, но я хотел бы попробовать и сделать это динамически, столбцы могут быть добавлены. Ниже приведен запрос, который будет лучшим способом сохранить его на моем SQL-сервере, чтобы я мог использовать его по мере необходимости?SQL Хранимая процедура с именами динамических столбцов

DECLARE @ColumnList AS Varchar(MAX) 
DECLARE @StartDate as Date 
DECLARE @EndDate as Date 
DECLARE @DepartmentID as Varchar(10) 
DECLARE @ColumnFilter as Varchar(3) 

SET @StartDate = '2015-01-01' 
SET @EndDate = '2015-05-01' 
SET @DepartmentID = 'GMC' 
SET @ColumnFilter = 'GM' 

SELECT @ColumnList = COALESCE(@ColumnList, ',') + c.name+',' FROM sys.columns c 
WHERE c.object_id = OBJECT_ID('tblDetails') AND c.Name LIKE @ColumnFilter + '%' 

SET @ColumnList = Left(@ColumnList,Len(@ColumnList)-1) 

DECLARE @Template AS Varchar(max) 
SET @Template = 'SELECT [RecordID] 
     ,[DateRecord] 
     ,[DepartmentID] 
     ,[Shift] 
     ,[ShiftLength] 
     ,[ShiftType] 
     ,[Active] 
     ,[Comment] 
     {ColumnList} 
    FROM [Data_Warehouse].[dbo].[tblDetails] 
    WHERE DateRecord >= ''{StartDate}'' AND DateRecord <= ''{EndDate}'' AND DepartmentID = ''{DepartmentID}'' 
    ORDER BY DateRecord' 

SET @Template = REPLACE(@Template, '{ColumnList}', @ColumnList) 
SET @Template = REPLACE(@Template, '{StartDate}', @StartDate) 
SET @Template = REPLACE(@Template, '{EndDate}', @EndDate) 
SET @Template = REPLACE(@Template, '{DepartmentID}', @DepartmentID) 

EXEC (@Template) 
+0

Что вы делаете с результатом в своем веб-приложении? Это отчет, который вы просто показываете для пользователей в datagrid? –

+0

Привет, Питер, я просто показываю данные в datagrid, чтобы пользователи могли видеть и экспортировать по мере необходимости. Я могу добавить это прямо в свой .NET-код и получить результаты, но не буду иметь несколько копий кода, плавающего в разных приложениях. –

ответ

1

Вы можете обернуть свой запрос в процедуру так же, как она есть. Затем вы можете выполнить его из своего приложения/сети и получить результат DataTable. При привязке к DataTable в DataGrid он должен автоматически оказывать столбцы в DataGrid

CREATE PROCEDURE GetDynamicReport 

    @StartDate as Date 
    ,@EndDate as Date 
    ,@DepartmentID as Varchar(10) 
    ,@ColumnFilter as Varchar(3) 
AS 
BEGIN 
    DECLARE @ColumnList AS Varchar(MAX) 

    SELECT @ColumnList = COALESCE(@ColumnList, ',') + c.name+',' FROM sys.columns c 
    WHERE c.object_id = OBJECT_ID('tblDetails') AND c.Name LIKE @ColumnFilter + '%' 

    SET @ColumnList = Left(@ColumnList,Len(@ColumnList)-1) 

    DECLARE @Template AS Varchar(max) 
    SET @Template = 'SELECT [RecordID] 
      ,[DateRecord] 
      ,[DepartmentID] 
      ,[Shift] 
      ,[ShiftLength] 
      ,[ShiftType] 
      ,[Active] 
      ,[Comment] 
      {ColumnList} 
     FROM [dbo].[tblDetails] 
     WHERE DateRecord >= ''{StartDate}'' AND DateRecord <= ''{EndDate}'' AND DepartmentID = ''{DepartmentID}'' 
     ORDER BY DateRecord' 

    SET @Template = REPLACE(@Template, '{ColumnList}', @ColumnList) 
    SET @Template = REPLACE(@Template, '{StartDate}', @StartDate) 
    SET @Template = REPLACE(@Template, '{EndDate}', @EndDate) 
    SET @Template = REPLACE(@Template, '{DepartmentID}', @DepartmentID) 

    EXEC (@Template); 

END 

GO 
-- Execute it like this 
EXEC dbo.GetDynamicReport 
    @StartDate = '2015-06-03 06:38:07', 
    @EndDate = '2015-06-03 06:38:07', 
    @DepartmentID = 'abc', 
    @ColumnFilter = 'GM' 

Вызов процедуры

public static DataTable CallReportProcedure(string connectionString, DateTime startDate, DateTime endDate, string departmentID, string columnFilter) 
{ 
    using(var conn = new SqlConnection(connectionString)) 
    using(var cmd = new SqlCommand("GetDynamicReport", conn) 
     { CommandType = System.Data.CommandType.StoredProcedure}) 
    { 
     cmd.Parameters.AddWithValue("@StartDate", startDate); 
     cmd.Parameters.AddWithValue("@EndDate", endDate); 
     cmd.Parameters.AddWithValue("@DepartmentID", departmentID); 
     cmd.Parameters.AddWithValue("@ColumnFilter", columnFilter); 

     var da = new SqlDataAdapter(cmd); 
     var ds = new DataSet(); 
     da.Fill(ds); 
     return ds.Tables[0]; 
    } 
} 

Тогда, если вам действительно нужно знать информацию о столбцах можно инспектировать в результате DataTable

static void Main(string[] args) 
     { 
      SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(); 
      builder.DataSource = "localhost"; 
      builder.InitialCatalog = "peter"; 
      builder.IntegratedSecurity = true; 
      var connectionString = builder.ConnectionString; 

      var resultTable = p.CallReportProcedure(connectionString, new DateTime(2015, 1, 1), new DateTime(2015, 5, 1), "GMC", "GM"); 
      // Bind the resultTable to your DataGrid 

      // If you need to know the column names then you can loop through the Columns of the resultTable 
      foreach (DataColumn col in resultTable.Columns) 
      { 
       // Print the names of the columns from the result 
       Console.WriteLine(col.ColumnName); 
      } 
     } 
+0

Спасибо, это сработало. Сначала я попытался запустить его со связанного сервера, но по какой-то причине я не смог получить список столбцов со связанного сервера. Добавление его на сервер, в котором таблица работает нормально. –

+0

Я думаю, что вы указали неправильный ответ –

+0

Просто заметили, что, спасибо. Изменили это. –

0

Вы можете создать представление только с нужными столбцами для этого запроса. когда нужные столбцы в запросе меняются, вы просто обновляете представление и альт, все ваши приложения теперь получают новый столбец, который вы хотите. Вам просто нужно убедиться, что ваши приложения могут иметь дело с разными потенциальными столбцами.

0

Хорошее решение - использовать для этого представление.

Другой вариант использования функции, но мы не можем обновить функцию после создания. Вот пример этого.

CREATE FUNCTION V_GetWarehouse (@StartDate Date,@EndDate Date,@DepartmentID varchar(10)) 
RETURNS TABLE 
AS 
RETURN 
SELECT [RecordID] 
    ,[DateRecord] 
    ,[DepartmentID] 
    ,[Shift] 
    ,[ShiftLength] 
    ,[ShiftType] 
    ,[Active] 
    ,[Comment]  
FROM [Data_Warehouse].[dbo].[tblDetails] 
WHERE DateRecord >= @StartDate AND DateRecord <= @EndDate AND [email protected] 

Так что используйте функцию View вместо функции.

Существует еще один лучший способ создать новую процедуру, а не просмотр. Вот пример

CREATE PROCEDURE sp_GetGenrealResult 
@ColumnName text, 
@TableName varchar(1000), 
@StartDate Date, 
@EndDate Date, 
@DepartmentID varchar(10) 
    AS 
enter code here 
     BEGIN 

    declare @DateRecordCol char(10)='DateRecord', 
     @DepartmentIDCol char(12)='DepartmentID' 
    Select @ColumnName from @TableName where @DateRecordCol >= @StartDate AND @DateRecordCol <= @EndDate AND @DepartmentIDCol [email protected] 
    END 

Выполнить это.

EXEC sp_GetGenrealResult '[RecordID],[DateRecord], [DepartmentID]', '[Data_Warehouse].[dbo]. [tblDetails]' , '2015-01-01', '2015-05-01' ,'GMC'