динамичен sql в съхранена процедура с име на колона като входен параметър

Имам тази съхранена процедура, която приема име на колона като inptu параметър. Операторът SELECT ще избере колона според входния параметър

create procedure getColumn (@whichColumn varchar)
as
begin
    declare @sql nvarchar(max) 
    set @sql = 'SELECT [' + @whichColumn + ']' 
        + ' FROM myTable'
        + ' where ['+ @whichColumn + '] is not null'
        + ' and [' + @whichColumn + '] != '''' ' ;
    exec sp_executesql @sql
end

Когато изпълня тази съхранена процедура,

exec getColumn 'Apple';

грешката казва "Невалидно име на колона 'A' ". Не мога да разбера защо получава само първия знак от входа


person kaboom    schedule 11.03.2014    source източник


Отговори (3)


Променете този ред

create procedure getClumn (@whichColumn varchar)

to

create procedure getClumn (@whichColumn varchar(max))

защото ако не сте присвоили размера на varchar по това време, той разглежда само един знак, така че получава само един знак A и генерира грешка.

person Pragnesh Khalas    schedule 11.03.2014
comment
Уау, нека не се увличаме и да отидем чак до VARCHAR(MAX) моето предположение е, че той вероятно се нуждае от по-малко от 8000 знака, за да постигне това. - person Zane; 11.03.2014
comment
@Zane Моето предположение е, че той никога няма да има нужда от повече от 128 :) - person M.Ali; 11.03.2014

Вижте декларацията на вашия параметър:

@whichColumn varchar

От MSDN:

Когато n не е указано в дефиниция на данни или израз за декларация на променлива, дължината по подразбиране е 1.

Така че това е една буква varchar. Опитайте се да посочите размер:

@whichColumn varchar(50)

Или дори по-добре, използвайте дефинирания от системата тип за имена на обекти:

@whichColumn sysname
person Andomar    schedule 11.03.2014
comment
^^^^Това е вашият отговор. Винаги декларирайте дължината на вашите колони. - person Zane; 11.03.2014
comment
Мислех, че е 30, ако не е спомената дължина :S - person M.Ali; 11.03.2014
comment
@M.Ali: Това е вярно, ако пропуснете дължината в cast и convert. Но в декларациите на променливи дължината по подразбиране е едно. Можете да гласувате тук, за да поправите лудостта. - person Andomar; 11.03.2014
comment
opss го обърка. :) Опитах се да гласувам, но няма да ми позволи, ще опитам по-късно. - person M.Ali; 11.03.2014
comment
/ въздишка, фактът, че това не е приетият отговор, е обезпокоителен. - person Zane; 11.03.2014

create procedure getColumn (@whichColumn nvarchar(128))   --<-- Maximum column name lenght
as
begin
    declare @sql nvarchar(max); 
    set @sql =   N'SELECT ' + QUOTENAME(@whichColumn)+ N' FROM myTable'
               + N' where '+ QUOTENAME(@whichColumn) + N' is not null'
               + N' and ' + QUOTENAME(@whichColumn)  +  N' != '''' ' ;
    exec sp_executesql @sql
end

Допълнителна бележка Използването на квадратни скоби във вашия конкатиниращ низ не е същото като използването на функцията QUOTENAME.

person M.Ali    schedule 11.03.2014
comment
Искате ли да оставите коментар всеки, който е гласувал против? - person M.Ali; 11.03.2014
comment
+1 към дисбаланс. Също така не съм сигурен защо имаш DV. - person Zane; 11.03.2014
comment
Наздраве, Зейн, има някои нумпти, които гласуват за забавление. Иска ми се да има система, при която всеки път, когато някои надолу гласуват нечестно, репутацията им да е -100 :S - person M.Ali; 11.03.2014
comment
М. Али Не знаех за TSQL ключовата дума QUOTENAME, докато не прочетох предложения от вас отговор. Това реши проблема, който имах при писането на динамичен SQL, за да задам име на колона в съхранена процедура UPDATE. Бонус е, че е по-чисто да се пише и разбира IMHO. - person Doreen; 25.03.2019