2012-04-10 1 views
21
create procedure sp_First 
@columnname varchar 
AS 
begin 
select @columnname from Table_1 
end 
exec sp_First 'sname' 

Мое требование - передавать имена столбцов в качестве входных параметров. Я пробовал, но это дало неправильный результат.Могу ли я передать имя столбца в качестве входного параметра в SQL хранимой Процедура

Помогите мне

+3

Вы можете выбрать лучший ответ на этот вопрос, текущий первый ответ вводит в заблуждение. – ctbrown

ответ

5

Это невозможно. Используйте либо динамическое SQL (опасное), либо гигантское выражение case (медленное).

+0

Если CASE находится только в инструкции SELECT (а не в предложении JOIN, WHERE, ORDER BY и т. Д.), То эта опция на самом деле медленная. – MatBailie

+1

Он будет вытаскивать все столбцы каждый раз, независимо от того, какая конкретная колонка запрашивается. – usr

9

Нет. Это просто выберет значение параметра. Вам нужно будет использовать динамический sql.

В вашей процедуры вы бы следующее:

DECLARE @sql nvarchar(max) = 'SELECT ' + @columnname + ' FROM Table_1'; 
exec sp_executesql @sql, N'' 
+3

он должен быть медленнее, не так ли? но сколько? можно ли его игнорировать? –

+1

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

2

Вы можете передать имя столбца, но вы не можете использовать его в SQL statemnt как

Select @Columnname From Table 

Можно было бы построить динамическую строку SQL и выполнить его как EXEC (@SQL)

Для получения дополнительной информации см. этот ответ на динамическом sql.

Dynamic SQL Pros and Cons

8

Попробуйте использовать динамический SQL:

create procedure sp_First @columnname varchar 
AS 
begin 
    declare @sql nvarchar(4000); 
    set @sql='select ['[email protected]+'] from Table_1'; 
    exec sp_executesql @sql 
end 
go 

exec sp_First 'sname' 
go 
45

Вы можете сделать это несколькими способами.

Во-первых, нужно создать запрос самостоятельно и выполнить его.

SET @sql = 'SELECT ' + @columnName + ' FROM yourTable' 
sp_executesql @sql 

Если вы выберете этот метод, будьте очень уверены в том, чтобы поместить ваш вход. Даже если вы знаете, что ваше приложение будет давать только «настоящие» имена столбцов, что, если кто-то обнаружит ошибку в вашей безопасности и сможет выполнить SP напрямую? Тогда они могут выполнить практически все, что им нравится. С динамическим SQL всегда, всегда, проверьте параметры.

В качестве альтернативы, вы можете написать сазе ...

SELECT 
    CASE @columnName 
    WHEN 'Col1' THEN Col1 
    WHEN 'Col2' THEN Col2 
       ELSE NULL 
    END as selectedColumn 
FROM 
    yourTable 

Это немного более долго наматывается, но в целом гораздо более безопасным.

+9

+1, 'Это немного более длинный, но намного более безопасный.' –

+0

Если вы получаете столбцы из другой таблицы «UpdateableColumns», вы также можете провести с ней какую-то проверку. Пример: «Где находится столбец (выберите ColumnName из UpdateableColumns)» – EduLopez

-5

Попробуйте с этим. Надеюсь, это сработает для вас.

Create Procedure Test 
(
    @Table VARCHAR(500), 
    @Column VARCHAR(100), 
    @Value VARCHAR(300) 
) 
AS 
BEGIN 

DECLARE @sql nvarchar(1000) 

SET @sql = 'SELECT * FROM ' + @Table + ' WHERE ' + @Column + ' = ' + @Value 

--SELECT @sql 
exec (@sql) 

END 

-----execution---- 

/** Exec Test Products,IsDeposit,1 **/ 
+0

Выберите *, не является хорошей практикой, и это не вызывает сомнения пользователя – Tiago

2
Create PROCEDURE USP_S_NameAvilability 
    (@Value VARCHAR(50)=null, 
     @TableName VARCHAR(50)=null, 
     @ColumnName VARCHAR(50)=null) 
     AS 
     BEGIN 
     DECLARE @cmd AS NVARCHAR(max) 
     SET @Value = ''''[email protected]+ '''' 
     SET @cmd = N'SELECT * FROM ' + @TableName + ' WHERE ' + @ColumnName + ' = ' + @Value 
     EXEC(@cmd) 
     END 

Как я попробовал один ответ, он становится выполнен успешно, но во время работы его не дает правильный вывод, вышеупомянутые работает хорошо

0

Как отметил MatBailie Это намного более безопасным так как это не динамический запрос, а ther - меньшие шансы на SQL-инъекцию. Я добавил одну ситуацию, когда вы даже хотите, чтобы предложение where было динамическим. XX YY являются именами столбцов

  CREATE PROCEDURE [dbo].[DASH_getTP_under_TP] 
    (
    @fromColumnName varchar(10) , 
    @toColumnName varchar(10) , 
    @ID varchar(10) 
    ) 
    as 
    begin 

    -- this is the column required for where clause 
    declare @colname varchar(50) 
    set @colname=case @fromUserType 
     when 'XX' then 'XX' 
     when 'YY' then 'YY' 
     end 
     select SelectedColumnId from (
     select 
      case @toColumnName 
      when 'XX' then tablename.XX 
      when 'YY' then tablename.YY 
      end as SelectedColumnId, 
     From tablename 
     where 
     (case @fromUserType 
      when 'XX' then XX 
      when 'YY' then YY 
     end)= ISNULL(@ID , @colname) 
    ) as tbl1 group by SelectedColumnId 

    end 
Смежные вопросы