从SQL server管理表中选择几行
我对SQL Server非常陌生。我正在尝试创建一个存储过程,以获得我需要的一些行。这是我的数据表: 假设我想展示所有具有TMS1和标识符88和89的车辆。我应该写什么?目前我有密码从SQL server管理表中选择几行,sql,sql-server,sql-server-2014,Sql,Sql Server,Sql Server 2014,我对SQL Server非常陌生。我正在尝试创建一个存储过程,以获得我需要的一些行。这是我的数据表: 假设我想展示所有具有TMS1和标识符88和89的车辆。我应该写什么?目前我有密码 ALTER Procedure [db_ddladmin].[spGetVehicles]@ECU nvarchar(20), @Identifier nvarchar(20) as Begin Select * FROM db_ddladmin.View_VehicleReadouts whe
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。我应该写什么?我可以使用OR语句,但这会给我重复的车辆,我不想要 可以使用列表作为由逗号分隔的参数。 然后在where子句中,您可以执行以下操作:
Identifier IN @IdentifierList
这样,您就可以从列表中选择多个记录。
这是你想要的吗
i、 e
假设我想展示所有具有TMS1和TMS1的车辆
标识符88和89
您可以使用用户定义的表类型:
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
如果潜在标识符的数量未知,则一个选项是将标识符作为逗号分隔的字符串传递。不幸的是,您将无法直接将逗号分隔的字符串与源表标识符进行比较,您必须首先将标识符字符串拆分为一个单独的表。这可以通过表值函数完成。我在堆栈溢出上找到了下面的拆分字符串代码示例,应该可以完成这项工作
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'
爱德蒙,这就是我的代码现在的样子
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的标识符是唯一的是的,这是我想要的。你能再解释一下吗?你能试一下并发布脚本吗?嗨,对不起,正在做一些事情,但我已经亲自尝试过了。检查此引用:对identifier子句执行类似于该线程答案的IN子句;所以你实际上是想说dinamic sqlWow谢谢你,我会试试这个,然后回来看看它是否有效。假设我想对ecu做同样的事情,假设我有不同的ecu,也有不同的标识符,这样行吗?我刚刚注意到我给出的示例中有一个错误。SplitString函数需要第二个参数,该参数定义字符串的分隔符(在本例中为逗号)。IN子句应如下所示:Identifier IN SELECT Item FROM[dbo].[SplitString]@Identifiers',“我已经更新了示例以反映更正。非常感谢@Edmond。我还有一个小问题。当我执行存储过程时,我得到一个包含ecu ebs7中标识符88,89的所有车辆的列表。但问题是它显示了双倍。例如,车辆Aura在ECu EBS7中同时具有标识88和89,因此在列表中它被列出两次。一次id为88,一次id为89,是否有办法只显示一次?我注意到一件事,如果我为ecu创建一个IN列表,假设我想要所有带有ecu EBS7和ALM1的车辆,当我执行存储过程时,我会得到所有威瑟尔拥有EBS7或ALM1或两者的车辆。我不想展示有ebs7但没有alm1的车辆。我只想列出同时具有alm1和EBS7的所有车辆。如果我正确理解您的第一个问题,您希望在ECu中获得与您的标识符匹配的车辆的不同记录。如果是这种情况,您可以简单地在中使用'DISTINCT'子句,但您必须将列限制为仅返回车辆和ECu。如果您想包括其他列,例如标识符列,该列在每个ECu和车辆中可能有多个条目,那么您首先必须决定如何处理这些列。例如,如果88和89都是Aura的有效标识符,那么您的记录中应该返回哪些标识符?或的问题只是括号:其中ECU=@ECU和identifier=90或identifier=91,另一个选项是说identifier in 90,91,这有助于避免优先级问题。
EXEC [db_ddladmin].[spGetVehicles] @ECU = 'EBS7, DIS2', @Identifiers = '88,94', @Value = '2459579, 8.0.0'