我是SQL Server的新手。我试图创建一个存储过程,让我得到一些我要求的行。这是我有的数据表:
所以,让我说我想展示所有拥有TMS1和标识符88和89的车辆。我该怎么写?目前我有代码
ALTER Procedure [db_ddladmin].[spGetVehicles]@ECU nvarchar(20),
@Identifier nvarchar(20)
as
Begin
Select * FROM db_ddladmin.View_VehicleReadouts where ECU = @ECU and Identifier = @Identifier
End
exec [db_ddladmin].[spGetVehicles] 'EBS7', '91'
这给了我所有带有ECU EBS7和标识符91的车辆。让我们在ECU EBS7上使用标识符90。我该怎么写?我可以使用OR语句,但这会给我重复的车辆,我不想要。
答案 0 :(得分:0)
您可以使用用户定义的表格类型:
create type dbo.YourNames as table (name varchar(10))
go
declare @names dbo.YourNames
insert into @names values ('ECU'),('EBS7')
select * from @names
select *
from db_ddladmin.View_VehicleReadouts v join @names on v.ECU = @names.name
答案 1 :(得分:0)
如果潜在标识符的数量未知,则一个选项是将标识符作为逗号分隔的字符串传递。遗憾的是,您将无法直接将逗号分隔的字符串与源表标识符进行比较,您首先必须将标识符字符串拆分为单独的表。这可以通过表值函数来完成。我在堆栈溢出处发现了以下拆分字符串代码示例,应该可以完成这项工作。
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[SplitString]
(@pString NVARCHAR(4000), @pDelimiter NCHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
WITH E1(N) AS (
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
), --10E+1 or 10 rows
E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
cteTally(N) AS (--==== This provides the "base" CTE and limits the number of rows right up front
-- for both a performance gain and prevention of accidental "overruns"
SELECT TOP (ISNULL(DATALENGTH(@pString),0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
SELECT 1 UNION ALL
SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
),
cteLen(N1,L1) AS(--==== Return start and length (for use in substring)
SELECT s.N1,
ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,8000)
FROM cteStart s
)
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l
WHERE SUBSTRING(@pString, l.N1, l.L1) <> ''
;
GO
将功能添加到数据库后,您可以按照以下步骤更新您的程序:
ALTER Procedure [db_ddladmin].[spGetVehicles]
(
@ECU nvarchar(20),
@Identifiers nvarchar(20)
)
AS
Begin
SELECT *
FROM db_ddladmin.View_VehicleReadouts where ECU = @ECU
and
Identifier IN (SELECT Item FROM [dbo].[SplitString]( @Identifiers, ',' ) )
END
您现在可以执行以下步骤:
EXEC [db_ddladmin].[spGetVehicles] @ECU = 'EBS7', @Identifiers = '88,89'
答案 2 :(得分:0)
Alter Procedure [db_ddladmin].[spGetVehicles]
(
@ECU nvarchar(20),
@Identifiers nvarchar(20),
@Value nvarchar(20)
)
AS
Begin
SELECT *
FROM db_ddladmin.View_VehicleReadouts where ECU IN (Select Item FROM [dbo].[SplitString](@ECU,',') )
and
Identifier IN (SELECT Item FROM [dbo].[SplitString]( @Identifiers, ',' ) )
and
Value in (Select Item From [dbo].[SplitString]( @Value, ',' ) );
with items(item) as (
select Item
from dbo.SplitString(@Value, ',') )
select Name
from db_ddladmin.View_VehicleReadouts
where Value in (select items.item from items)
group by Name
having count(distinct value) = (select count(*) from items);
END
我使用
执行EXEC [db_ddladmin].[spGetVehicles] @ECU = 'EBS7, DIS2', @Identifiers = '88,94', @Value = '2459579, 8.0.0'
如果我只使用一个ECU。有用。例如,如果我有EBS7,那就是结果:
正如你可以看到的那样,当我只有一个ECU写入时它可以正常工作,但是当我尝试使用两个ECU时它没有工作,有什么建议吗?
为了您的信息,所有ecu都与某些标识符相关联。所有标识符都有一些特定的值,这些值对于该ECU的标识符是唯一的
答案 3 :(得分:-1)
您可以使用列表作为逗号分隔的参数。 然后在你的where子句中,你可以这样做:
Identifier IN @IdentifierList
通过这种方式,您可以从列表中选择多个记录。 这是你想要的吗?
即。
所以,假设我想展示所有拥有TMS1和TMS1的车辆 标识符88和89
EXEC [db_ddladmin].[spGetVehicles] 'TMS1', '88,89'