我是T-SQL的新手。所以,请帮我写一下sql。
我有桌子价格(代码栏是主要栏目):
Code Value
A1 234
A2 525
A3 566
我将输入一个字符串,而sql需要返回一个表。
Ex1:输入'A2' - >返回:
Code Value
A2 525
Ex2:输入'A1 A3' - >返回:
Code Value
A1 234
A3 566
Ex3:输入'A1 A3 A1' - >返回:
Code Value
A1 234
A3 566
Ex4:输入'A1 A4' - >返回:
Code Value
A1 234
请帮帮我。我正在使用SQL Server 2005.Tks。
答案 0 :(得分:2)
SELECT [Price].Code, [Price].Value FROM [Price] WHERE [Price].Code IN ('A1', 'A2');
它非常有效,但它有两个限制:
您不能在IN
子句中使用常规SQL参数,因此您可以自动将其附加到SQL字符串,在某些情况下,可以打开SQL注入。
这不完全是您要求的输入格式:而不是A2 A2
它是'A1', 'A2'
。
祝你好运!
编辑:如果您真的想使用A1 A2
格式,则无法使用IN
并且您必须拆分字符串,然后检查它是否包含当前[Price].Code
。请注意,它的效果远远低于我的第一个例子。
默认情况下,T-SQL不支持Split
,因此您必须手动添加它:
CREATE FUNCTION [dbo].[Split]
(
@RowData NVARCHAR(MAX),
@Delimeter NVARCHAR(MAX)
)
RETURNS @RtnValue TABLE
(
ID INT IDENTITY(1,1),
Data NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @Iterator INT
SET @Iterator = 1
DECLARE @FoundIndex INT
SET @FoundIndex = CHARINDEX(@Delimeter,@RowData)
WHILE (@FoundIndex>0)
BEGIN
INSERT INTO @RtnValue (data)
SELECT
Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))
SET @RowData = SUBSTRING(@RowData,
@FoundIndex + DATALENGTH(@Delimeter) / 2,
LEN(@RowData))
SET @Iterator = @Iterator + 1
SET @FoundIndex = CHARINDEX(@Delimeter, @RowData)
END
INSERT INTO @RtnValue (Data)
SELECT Data = LTRIM(RTRIM(@RowData))
RETURN
END
然后,你可以这样做:
SELECT [Price].Code, [Price].Value FROM [Price]
JOIN Split(@Codes, ' ') AS [Code]
ON [Code].Data = [Price].Code
答案 1 :(得分:0)
正如Alon所提到的,您需要一个函数或查询来将值拆分为表中的行。另一种方法是使用Numbers表,该表可以是静态的,也可以作为公用表表达式的一部分创建:
Declare @Alist varchar(50);
Declare @Delimiter char(1);
Declare @DelimiterLength int;
Set @Delimiter = ' ';
Set @DelimiterLength = DataLength(@Delimiter);
Set @Alist = 'A1 A2 A3';
Set @Alist = @Delimiter + @Alist + @Delimiter;
With Numbers As
(
Select Row_Number() Over ( Order By C1.object_id ) As Value
From sys.columns As C1
Cross Join sys.columns As C2
)
Select CharIndex(@Delimiter, @Alist, N.Value) + @DelimiterLength As Position
, Substring (
@Alist
, CharIndex(@Delimiter, @Alist, N.Value) + @DelimiterLength
, CharIndex(@Delimiter, @Alist, N.Value + 1)
- ( CharIndex(@Delimiter, @Alist, N.Value) + @DelimiterLength )
) As Value
From Numbers As N
Where N.Value Between 1 And ( Len(@Alist) - 1 )
And Substring(@Alist, N.Value, @DelimiterLength) = @Delimiter
Order By N.Value
这里的空格分隔符存在一个小问题。 Len
函数在其确定中忽略空格,因此我使用了DataLength
函数,并确保将@Delimiter
声明为varchar
而不是nvarchar
。 DataLength
将返回字符串中的字节数,该字节数将是nvarchar
的一般字符数的两倍。
Numbers CTE(或者它可以是一个静态表)只是一个连续整数的静态列表,对于像这样的情况非常有用。
这种方法也可以合并到一般查询中,您可以在其中分析另一个表中的每一行,如下所示:
With Numbers As
(
Select Row_Number() Over ( Order By C1.object_id ) As Value
From sys.columns As C1
Cross Join sys.columns As C2
)
Select CharIndex(@Delimiter, A.List, N.Value) + @DelimiterLength
, Substring (
A.List
, CharIndex(@Delimiter, A.List, N.Value) + @DelimiterLength
, CharIndex(@Delimiter, A.List, N.Value + 1)
- ( CharIndex(@Delimiter, A.List, N.Value) + @DelimiterLength )
)
From Numbers As N
Cross Join ( Select A1.List From SomeTable ) As A
Where N.Value Between 1 And ( Len(A.List) - 1 )
And Substring(A.List, N.Value, @DelimiterLength) = @Delimiter
Order By N.Value