Ro'yxatni o'zida saqlab turishda parametr sifatida qanday qilib o'tkazaman?

Ro'yxat nomlarini qaytarish uchun foydalanuvchi identifikatorlari ro'yxatini ko'rishni qidiryapsiz. Chiqarilgan nomlarni (COALESCE yoki boshqa narsalar bilan) tuzish rejasi bor, lekin foydalanuvchi identifikatorlari ro'yxatiga o'tishning eng yaxshi usulini topishga harakat qilaman. Sprokning jasadlari shu kabi ko'rinishga ega bo'ladi:

create procedure [dbo].[get_user_names]
@user_id_list, --which would equal a list of incoming ID numbers like (5,44,72,81,126)
@username varchar (30) output
as
select last_name+', '+first_name 
from user_mstr
where user_id in @user_id_list

@User_id_list uchun qadriyatlarim bu erda mening asosiy tashvishim.

9
ID identifikatorlari ro'yxatidan o'tmagan bo'lar edim, men foydalanuvchi tomonidan belgilangan jadval turi yaratib, qiymatlarni ichiga kiritib, u o'zgaruvchini procga o'tkazib yuborardim. Keyin jadvalga JOIN ni kiritishingiz mumkin.
qo'shib qo'ydi muallif Siyual, manba
jadval parametrlari bilan rozi bo'ldim ... ikkinchidan, mag'lubiyatni ajratuvchi va so'nggi chora sifatida foydalanaman ... dinamik sql. Shu kabi savol to'g'ridan-to'g'ri bu erda yuborildi.
qo'shib qo'ydi muallif scsimon, manba
Dasturlash tiliga va APIga qarab ro'yxatni jadval qiymatli parametr (TVP) sifatida qabul qilishingiz mumkin. Boshqa echimlar SQL Server versiyasiga qarab farqlanadi. sommarskog.se/arrays-in-sql.html ga qarang.
qo'shib qo'ydi muallif Dan Guzman, manba
Bu qanday qilib siz uni chaqirayotganingizga bog'liq. Iltimos, savolingizni tahrirlang va uni qanday qilib chaqirayotganingizni tushuntiring. (C # ning ichki SQL-dan hisobot berish vositasi?). Shuningdek, versiya haqida batafsil ma'lumot oling. Ba'zi versiyalarda string_split dan foydalanishingiz mumkin
qo'shib qo'ydi muallif Nick.McDermaid, manba
bu erga qarashga harakat qiling: " stackoverflow.com/questions/7097079/…
qo'shib qo'ydi muallif Justin C, manba

6 javoblar

SQL serverida saqlangan amaliyotga bir qator qiymatlarni kiritish uchun afzal qilingan uslub jadval qiymatlari parametrlaridan foydalanishdir.

Avval shunday turni aniqlang:

CREATE TYPE UserList AS TABLE ( UserID INT );

Keyin saqlangan amaliyotda ushbu turdan foydalanasiz:

create procedure [dbo].[get_user_names]
@user_id_list UserList READONLY,
@username varchar (30) output
as
select last_name+', '+first_name 
from user_mstr
where user_id in (SELECT UserID FROM @user_id_list)

Shunday qilib, ushbu saqlangan amaliyotni chaqirishdan oldin, jadval o'zgaruvchisini to'ldirasiz:

DECLARE @UL UserList;
INSERT @UL VALUES (5),(44),(72),(81),(126)

Va nihoyat, SPga qo'ng'iroq qiling:

EXEC dbo.get_user_names @UL, @username OUTPUT;
21
qo'shib qo'ydi

Aytishim mumkinki, uchta asosiy ishtirokchi bor: jadval-qimmatli parametrlar, ajratilgan ro'yxat satrlari va JSON dizayni.

Since 2016, you can use the built-in STRING_SPLIT if you want the delimited route: https://docs.microsoft.com/en-us/sql/t-sql/functions/string-split-transact-sql

Ehtimol, bu eng oson/eng oddiy/oddiy yondashuv bo'lar edi.

Bundan tashqari, 2016 yildan boshlab, JSON nvarchar sifatida qabul qilinishi va OPENJSON bilan ishlatilishi mumkin: https://docs.microsoft.com/en-us/sql/t-sql/functions/openjson-transact-sql

O'zingizning sxema bo'yicha sezilarli o'zgarib ketishi mumkin bo'lgan ma'lumotlarni tuzish uchun tuzilgan ma'lumotlar to'plamingiz bo'lsa, ehtimol, bu yaxshi.

TVPs, ko'proq tuzilgan parametrlarni o'tkazishning kanonik usuli bo'lib tuyuladi va agar siz ushbu tuzilish, aniqlik va asosiy qiymat/tiplarni tekshirishga muhtoj bo'lsangiz, ular hali ham yaxshi. Biroq, iste'molchi tomonida biroz og'irroq bo'lishi mumkin. Agar sizda 2016+ yo'q bo'lsa, bu ehtimol standart/eng yaxshi variant.

Menimcha, bu sizning ushbu konkret fikrlarning har biri bilan savdo-sotiqdir, shuningdek sizning parametrlaringizning tuzilishi haqida aniq ma'lumotga ega bo'lishingiz afzaldir, ya'ni sizda 2016+ bo'lsa ham, siz parametrning turi/sxemasini aniqroq belgilashni afzal ko'rishingiz mumkin mag'lubiyatga o'tadi va uni biroz ajralib chiqadi.

4
qo'shib qo'ydi

Buni sinashingiz mumkin:

create procedure [dbo].[get_user_names]
    @user_id_list varchar(2000), -- You can use any max length

    @username varchar (30) output
    as
    select last_name+', '+first_name 
    from user_mstr
    where user_id in (Select ID from dbo.SplitString( @user_id_list, ',') )

Va bu erda foydalanuvchi SplitString funksiyasini aniqladi:

Create FUNCTION [dbo].[SplitString]
(    
      @Input NVARCHAR(MAX),
      @Character CHAR(1)
)
RETURNS @Output TABLE (
      Item NVARCHAR(1000)
)
AS
BEGIN
      DECLARE @StartIndex INT, @EndIndex INT

      SET @StartIndex = 1
      IF SUBSTRING(@Input, LEN(@Input) - 1, LEN(@Input)) <> @Character
      BEGIN
            SET @Input = @Input + @Character
      END

      WHILE CHARINDEX(@Character, @Input) > 0
      BEGIN
            SET @EndIndex = CHARINDEX(@Character, @Input)

            INSERT INTO @Output(Item)
            SELECT SUBSTRING(@Input, @StartIndex, @EndIndex - 1)

            SET @Input = SUBSTRING(@Input, @EndIndex + 1, LEN(@Input))
      END

      RETURN
END
1
qo'shib qo'ydi
Bu sizning funktsiyangiz turiga nisbatan eng sekin yetsin. Boshqa variantlar uchun bu yerni tekshiring: Split satrlarni to'g'ri yo'l - yoki keyingi eng yaxshi usul - Aaron Bertran
qo'shib qo'ydi muallif SqlZim, manba
ular, ehtimol, mag'lubiyatga ajratish funksiyasiga muhtoj .....
qo'shib qo'ydi muallif scsimon, manba
dbo.SplitString ichki funktsiya emas.
qo'shib qo'ydi muallif ahmed abdelqader, manba

Ehtimol foydalanishingiz mumkin:

select last_name+', '+first_name 
from user_mstr
where ',' + @user_id_list + ',' like '%,' + convert(nvarchar, user_id) + ',%'
0
qo'shib qo'ydi

String_list_type parametrini yaratish uchun ushbu oddiy "inline" usuldan foydalanishingiz mumkin (SQL Server 2014 da ishlaydi):

declare @p1 dbo.string_list_type
insert into @p1 values(N'myFirstString')
insert into @p1 values(N'mySecondString')

Saqlangan trekni bajarishda namunali foydalanish:

exec MyStoredProc @[email protected]
0
qo'shib qo'ydi

Men ushbu muammoni quyidagicha hal qildim:

  1. C# da String o'zgaruvchisini yaratdim.

string userId = "";

  1. Ro'yxatning elementini ushbu o'zgaruvchiga qo'ydim.
  2. 'ni ajratib qo'ydim

, masalan: C# da

  userId = "5,44,72,81,126";
 
-ni tanlang

va SQL-Serverga jo'natish

 SqlParameter = param = cmd.Parameters.AddWithValue ("@ user_id_list", userId);
 
-ni tanlang
  1. SQL-serverda ajratilgan funktsiyani yarataman. Qabul qilingan ro'yxatni (uning turi NVARCHAR (Maks) ) jadvalga aylantirish uchun)
  CREATE FUNCTION dbo.SplitInts dan foydalaning
(
   @List VARCHAR (MAX),
   @Delimiter VARCHAR (255)
)
Qaytaring jadvali
AS
  RETURN (Applications Item = CONVERT (INT, Item) FROM dan foydalaning
      (SELECT Item = x.i.value ('(./Text ()) [1]', 'varchar (max)')
        FROM (Tanlash [XML] = CONVERT (XML, ''
        REPLACE (@List, @Delimiter, ' ') + '') so'rovlar ('.')
          ). [XML] .nodes ("i") AS x (i)) AS y
      WHERE element NULL emas
  );
 
-ni tanlang
  1. Quyidagi buyruqni ishlatib, Magistrlik protsedurasida kirish ro'yxatini ishlataman.

SELECT user_id = FROM dan dbo.SplitInts (@user_id_list, ',');

0
qo'shib qo'ydi