webForumDet fria alternativet

Return multiple value?

Databaser & SQL

26 svar · 3 124 visningar · startad av harry_boy

Medlem sedan feb. 2003193 inlägg
Frågan#1

Jag försöker skapa följande trigger:

CREATE TRIGGER [dbo].[FreightSearch] 
ON [dbo].[Ord]
FOR UPDATE
AS

BEGIN 
  SET NOCOUNT ON;

UPDATE Ord
SET Web = (SELECT CONCAT(Stc.Ad4, Ord.OrdNo) AS Freight_Search FROM Ord INNER JOIN Stc ON Ord.OrdNo = Ord.OrdNo)
        
END  
GO

Men jag får felmeddelande att jag försöker sätta in "multiple value". Någon som ser vad jag gör för nybörjarfel?

Medlem sedan aug. 20039 340 inlägg
#2
ON Ord.OrdNo = Ord.OrdNo

Detta gör att alla rader väljs ur tabellen. Du måste använda unika namn för tabellnamnen. Du kan åstadkomma detta med ett alias, som du kan skapa med AS även för tabellnamn.

UPDATE Ord
SET Web = (SELECT CONCAT(Stc.Ad4, Ord.OrdNo) AS Freight_Search FROM [u]Ord AS Ord2[/u] INNER JOIN Stc ON [u]Ord.OrdNo = Ord2.OrdNo[/u])

(Inga garantier att koden i övrigt är korrekt.)

Sen borde du kunna göra detta med en UPDATE+JOIN utan inre select, men det är en annan femma.

Medlem sedan feb. 2003193 inlägg
#3

Hejsan och tack nitro2k01.

Jag fick tyvärr samma problem.

"... returned more than 1 value. This is permitted when the subquery follows ....."

Hur skulle update+join kunna se ut? Jag adderar ju värden från två olika kolumner till kolumnen web. Och jag vill ju att ordno ska tas från den ordern jag står på.

Medlem sedan juni 200032 967 inlägg
#4

Hur hänger tabellerna Stc och Ord ihop? Ordno?
Måste du verkligen joina?

UPDATE Ord
SET Web = 
      (SELECT CONCAT(Ad4, inserted.Ordno) FROM Stc WHERE Ordno = inserted.Ordno)
WHERE Ordno = inserted.Ordno

Och slutligen kanske du ska fundera på om det är rätt ställe att konkatenera på - kanske ska du göra det i presentationen istället?

mvh

Medlem sedan aug. 20039 340 inlägg
#5

Vänta nu, du har ju inget villkor på Stc, så du joinar alla rader i den tabellen! Menade du kanske Stc.OrdNo = Ord.OrdNo? Eller förresten efter lite googlande verkar det som du måste använda dig av nyckelordet INSERTED för att få reda på vad som har uppdaterats.
Efter samma googlande tror jag även att du ska ha AFTER UPDATE istället för FOR UPDATE.

Prova:

CREATE TRIGGER [dbo].[FreightSearch] 
ON [dbo].[Ord]
AFTER UPDATE
AS

BEGIN 
  SET NOCOUNT ON;

UPDATE Ord
SET Web = CONCAT(Stc.Ad4, Ord.OrdNo) 
WHERE inserted.OrdNo = Ord.OrdNo
INNER JOIN Stc ON Stc.OrdNo = Ord.OrdNo

END  
GO

Jag skriver denna kod utan att kunna testa den och utan att egentligen veta sen innan hur saker funkar i MS SQL, men förhoppningsvis kommer det att gå att få koden att funka till slut. :)

Medlem sedan feb. 2003193 inlägg
#6

Det är min okunskap som lyser igenom. Det är naturligtvis Ord.FrStc som ska vara samma som Stc.FrStc.

Hur menar du "Och slutligen kanske du ska fundera på om det är rätt ställe att konkatenera på - kanske ska du göra det i presentationen istället?"?

Medlem sedan juni 200032 967 inlägg
#7

Det jag menar är: Någonstans visar du datat, antar jag. Kanske är det bättre att göra konkateneringen / joinen där, istället för att lagra ett färdigkonkatenerat värde. Jag säger inte att det är rätt - jag vet ju ingenting om ditt system - men jag bara säger att du kan fundera på det. :)

Medlem sedan feb. 2003193 inlägg
#8

Ok jag förstår.

Jag måste lagra datat på detta sätt då jag inte kan påverka hur det ska visas..

Medlem sedan juni 200032 967 inlägg
#9

Dåså, då är det rätt approach. :-)

Det finns flera sätt att göra en dylik update på - kanske hade jag valt att göra så här:

DECLARE @Web VARCHAR(50)

SELECT @Web = CONCAT(Stc.Ad4, Ord.OrdNo) 
FROM Stc 
INNER JOIN Ord 
   ON St.FrStc = Ord.FrStc
WHERE Ord.OrdNo = inserted.OrdNo

UPDATE Ord SET Web = @Web WHERE OrdNo = inserted.OrdNo

mvh

Medlem sedan feb. 2003193 inlägg
#10

När jag kör detta så får jag

Msg 4104, Level 16, State 1, Procedure FreightSearch, Line 17
The multi-part identifier "insterted.OrdNo" could not be bound.

Och rad 17 är

rad 2 i nedan
UPDATE Ord SET Web = @Web
WHERE OrdNo = insterted.OrdNo

Medlem sedan feb. 2003193 inlägg
#11

Ord.OrdNo är primärnyckel och int, not null
Ord.Web är varchar(260), not null
Stc.StcNo är primär, int, not null
Stc.Ad4 är varchar(60), not null

har det något med skillnaden i datatyp att göra?

Jag ser också att jag stavade fel till inserted och skrev insterted men det kvittade när jag ändade jag fick samma fel.

Medlem sedan feb. 2003193 inlägg
#12

Jag uppdaterade till följande:

UPDATE Ord SET Web = @Web FROM inserted
WHERE Ord.OrdNo = Inserted.OrdNo

Och då fungerar det och den uppdaterar enbart den raden man sparar om. Men problemet är att i inserted verkar ligga det ett statiskt värde sedan tidigare (talet 282, från en tidigare order). Nu när jag sparar en annan order så får den samma rad. Dvs ad4 samt ordernr282 vilket är fel. Jag vill ju att den ska få det ordernr som kommer från den raden som sparas.

Medlem sedan feb. 2003193 inlägg
#13

Så här ser nu koden ut:

CREATE TRIGGER [dbo].[FreightSearch] 
ON [DB1].[dbo].[Ord]
AFTER UPDATE
AS

BEGIN 
  SET NOCOUNT ON;

DECLARE @Web VARCHAR(260)

SELECT @Web = CONCAT(Stc.Ad4, Ord.OrdNo) 
FROM Stc 
INNER JOIN Ord 
   ON Stc.StcNo = Ord.FrStc

UPDATE Ord SET Web = @Web FROM inserted
WHERE  Ord.OrdNo = inserted.OrdNo
   
END  
GO

Och sparar jag en ny order så blir det rätt. Men sparar jag om en gammal så ersätts "OrdNo" med den senast nya order.

Vad är fel som gör att jag inte får med mig ordno från aktuella ordern jag uppdaterar eller sparar?

Medlem sedan feb. 2003193 inlägg
#14

Snälla rara är det ingen som kan hjälpa mig med vad jag eventuellt gör för fel.

Jättetack på förhand.

Medlem sedan aug. 20039 340 inlägg
#15

I select-satsen så har du inget som knyter ihop ordern med det id som just har lagts in. Prova:

CREATE TRIGGER [dbo].[FreightSearch] 
ON [DB1].[dbo].[Ord]
AFTER UPDATE
AS

BEGIN 
  SET NOCOUNT ON;

DECLARE @Web VARCHAR(260)

SELECT @Web = CONCAT(Stc.Ad4, inserted.OrdNo) 
FROM Stc 
WHERE Stc.StcNo = inserted.FrStc

UPDATE Ord SET Web = @Web FROM inserted
WHERE  Ord.OrdNo = inserted.OrdNo
   
END  
GO
Medlem sedan feb. 2003193 inlägg
#16

Tack nitro2k01 men fick tyvärr följande fel

Msg 4104, Level 16, State 1, Procedure FreightSearch, Line 13
The multi-part identifier "inserted.FrStc" could not be bound.
Msg 4104, Level 16, State 1, Procedure FreightSearch, Line 11
The multi-part identifier "inserted.OrdNo" could not be bound.

Medlem sedan feb. 2003193 inlägg
#17

Jag har fått allt att fungera nu i min demo-miljö men när jag skulle använda den på en annan installation så säger den att CONCAT inte fungerar i SQL 2008 :-( Felmeddelandet är enligt följande:

'CONCAT' is not a recognized built-in function name.

CREATE TRIGGER [dbo].[FreightSearch] 
ON [DB1].[dbo].[Ord]

AFTER UPDATE
AS

BEGIN 
  SET NOCOUNT ON;

DECLARE @Web VARCHAR(260)

SELECT @Web = CONCAT(Stc.Ad4, inserted.OrdNo) 
FROM Stc 
JOIN inserted
ON Stc.StcNo = inserted.FrStc

UPDATE Ord SET Web = @Web FROM inserted
WHERE  Ord.OrdNo = inserted.OrdNo
AND Ord.TrTp = '1'
   
END  
GO

Jag som blev så glad att det fungerar. Men hur gör jag för att skriva om det till SQL 2008

Medlem sedan juni 200032 967 inlägg
#18

Prova att bara konkatenera med +.

Stc.Ad4 + Convert(nvarchar(10), inserted.OrdNo)
Medlem sedan feb. 2003193 inlägg
#19

Gör jag det så får jag

Msg 156, Level 15, State 1, Procedure FreightSearch, Line 20
Incorrect syntax near the keyword 'FROM'.

Och koden ser ut

SELECT @WebPg = CONCAT(Stc.Ad4 + Convert(nvarchar(10), inserted.OrdNo) 
FROM Stc 
JOIN inserted
ON Stc.StcNo = inserted.FrStc
Medlem sedan juni 200032 967 inlägg
#20

Nej, bort med concat alltså. Så här tänkte jag:

SELECT @WebPg = Stc.Ad4 + Convert(nvarchar(10), inserted.OrdNo) 
FROM Stc 
JOIN inserted
ON Stc.StcNo = inserted.FrStc

mvh

268 ms totalt · 4 externa anrop · v20260731065814-full.6fe65c25
123 ms — deklarationer (db)
0 ms — hämta statistik (cache)
139 ms — hämta tråd, inlägg och bilagor (db)
127 ms — ändringar (db)