1

SQL スクリプトで使用したいコンマで区切られた数字の varchar 文字列がありますが、データベースの bigint フィールドと比較する必要があります。それを変換するために知っておく必要があります:

DECLARE @RegionID varchar(200) = null
SET @RegionID = '853,834,16,467,841,460,495,44,859,457,437,836,864,434,86,838,458,472,832,433,142,154,159,839,831,469,442,275,840,299,446,220,300,225,227,447,301,450,230,837,441,835,302,477,855,411,395,279,303'

SELECT a.ClassAdID,    -- 1
        a.AdURL,        -- 2
        a.AdTitle,      -- 3
        a.ClassAdCatID, -- 4
        b.ClassAdCat,   -- 5
        a.Img1,         -- 6
        a.AdText,       -- 7
        a.MemberID,     -- 9
        a.Viewed,       -- 10
        c.Domain,       -- 11
        a.CreateDate    -- 12
        FROM ClassAd a  
        INNER JOIN ClassAdCat b ON b.ClassAdCAtID = a.ClassAdCAtID
        INNER JOIN Region c ON c.RegionID = a.RegionID
        AND a.PostType = 'CPN'
        AND DATEDIFF(d, GETDATE(), ExpirationDate) >= 0
        AND a.RegionID IN (@RegionID)
        AND Viewable = 'Y'

これは次のエラーで失敗します。

Error converting data type varchar to bigint.

RegionID データベースには bigint フィールドがあります。varchar を bigint に変換する必要があります。アイデアはありますか?

よろしくお願いします。

ネオジャキー

4

6 に答える 6

4

この関数を作成します。

CREATE function [dbo].[f_split]
(
@param nvarchar(max), 
@delimiter char(1)
)
returns @t table (val nvarchar(max), seq int)
as
begin
set @param += @delimiter

;with a as
(
select cast(1 as bigint) f, charindex(@delimiter, @param) t, 1 seq
union all
select t + 1, charindex(@delimiter, @param, t + 1), seq + 1
from a
where charindex(@delimiter, @param, t + 1) > 0
)
insert @t
select substring(@param, f, t - f), seq from a
option (maxrecursion 0)
return
end

この部分を変更します。

AND a.RegionID IN (select val from dbo.f_split(@regionID, ','))

これを変更して、全体的なパフォーマンスを向上させます。

AND DATEDIFF(d, 0, GETDATE()) <= ExpirationDate
于 2012-10-16T15:01:35.637 に答える
1

あなたのクエリは、それらが別々の値であることを知りません。これには動的SQLを使用できます。

DECLARE @RegionID varchar(200) = null
SET @RegionID = '853,834,16,467,841,460,495,44,859,457,437,836,864,434,86,838,458,472,832,433,142,154,159,839,831,469,442,275,840,299,446,220,300,225,227,447,301,450,230,837,441,835,302,477,855,411,395,279,303'

declare @sql nvarchar(Max)

set @sql = 'SELECT a.ClassAdID,    -- 1
        a.AdURL,        -- 2
        a.AdTitle,      -- 3
        a.ClassAdCatID, -- 4
        b.ClassAdCat,   -- 5
        a.Img1,         -- 6
        a.AdText,       -- 7
        a.MemberID,     -- 9
        a.Viewed,       -- 10
        c.Domain,       -- 11
        a.CreateDate    -- 12
        FROM ClassAd a  
        INNER JOIN ClassAdCat b ON b.ClassAdCAtID = a.ClassAdCAtID
        INNER JOIN Region c ON c.RegionID = a.RegionID
        AND a.PostType = ''CPN''
        AND DATEDIFF(d, GETDATE(), ExpirationDate) >= 0
        AND a.RegionID IN ('+@RegionID+')
        AND Viewable = ''Y'''

exec sp_executesql @sql
于 2012-10-16T15:02:22.563 に答える
1

私は時々このアプローチを使用しますが、とても良いと思います。コンマ区切りの文字列を AUX テーブル (#ARRAY と呼ばれる) に変換し、AUX テーブルに基づいてメイン テーブルにクエリを実行します。

declare @RegionID varchar(50)
SET @RegionID = '853,834,16,467,841,460,495,44,859,457,437,836,864,434,86,838,458,472,832,433,142,154,159,839,831,469,442,275,840,299,446,220,300,225,227,447,301,450,230,837,441,835,302,477,855,411,395,279,303'
declare @S varchar(20)
if LEN(@RegionID) > 0 SET @RegionID = @RegionID + ',' 
CREATE TABLE #ARRAY(region_ID VARCHAR(20))

WHILE LEN(@RegionID) > 0 BEGIN
   SELECT @S = LTRIM(SUBSTRING(@RegionID, 1, CHARINDEX(',', @RegionID) - 1))
   INSERT INTO #ARRAY (region_ID) VALUES (@S)
   SELECT @RegionID = SUBSTRING(@RegionID, CHARINDEX(',', @RegionID) + 1, LEN(@RegionID))
END

select * from your_table
where regionID IN (select region_ID from #ARRAY)

クエリ文字列を連結してからEXECを使用して実行する必要がなくなりますが、これはあまり良いアプローチではないと思います。

コードを 2 回実行する必要がある場合は、一時テーブルを削除する必要があります。

于 2012-10-16T15:13:32.363 に答える
0

答えは単純に保つべきだと思います。
次のようにCHARINDEXを使用してみてください。

DECLARE @RegionID VARCHAR(200) = NULL 

SET @RegionID = 
'853,834,16,467,841,460,495,44,859,457,437,836,864,434,86,838,458,472,832,433,142,154,159,839,831,469,442,275,840,299,446,220,300,225,227,447,301,450,230,837,441,835,302,477,855,411,395,279,303'

SELECT 1 
WHERE  Charindex('834', @RegionID) > 0 

SELECT 1 
WHERE  Charindex('999', @RegionID) > 0 

大きな文字列変数で値がCHARINDEX見つかると、その位置が返されます。それ以外の場合は、0が返さ
れます。これを検索ツールとして使用します。

于 2012-10-16T15:19:59.510 に答える
0

私はディエゴの答えが好きですが、実際のテーブルを作成するのではなく、テーブル変数を宣言しているので、私の変更は少し良いと思います。「in」ステートメントが少し遅くなる可能性があることはわかっているので、とにかく Company テーブルからの情報が必要だったので、内部結合を行いました。

declare @companyIdList varchar(1000)
set @companyIdList = '1,2,3'

if LEN(@companyIdList) > 0 SET @companyIdList = @companyIdList + ',' 
declare @CompanyIds TABLE (CompanyId bigint)
declare @S varchar(20)
WHILE LEN(@companyIdList) > 0 BEGIN
   SELECT @S = LTRIM(SUBSTRING(@companyIdList, 1, CHARINDEX(',', @companyIdList) - 1))
   INSERT INTO @CompanyIds (CompanyId) VALUES (@S)
   SELECT @companyIdList = SUBSTRING(@companyIdList, CHARINDEX(',', @companyIdList) + 1, LEN(@companyIdList))
END

select d.Id, d.Name, c.Id, c.Name 
from [Division] d 
    inner join [Company] c on d.CompanyId = c.Id
    inner join @CompanyIds cids on c.Id = cids.CompanyId
于 2013-06-17T18:15:29.350 に答える
0

このクエリを変更する最も簡単な方法は、IN関数を文字列関数に置き換えることです。これが私が使用する最も安全なアプローチであると考えているものですLIKE(これはデータベース間で移植可能です):

    AND ','+@RegionID+',' like '%,'+cast(a.RegionID as varchar(255))+',%'

またはCHARINDEX:

    AND charindex(','+cast(a.RegionID as varchar(255))+',', ','+@RegionID+',') > 0

ただし、リストをコードに明示的に配置する場合は、一時テーブルを使用しないでください。

declare @RegionIds table (RegionId int);
insert into @RegionIds
    select 853 union all
    select 834 union all
    . . .
    select 303

IN次に、句でテーブルを使用できます。

   AND a.RegionId in (select RegionId from @RegionIds)

またはJOIN節で。

于 2012-10-16T15:27:34.170 に答える