Hỏi về trigger

  1. Em có bảng stock là sl tồn kho theo từng id sản phẩm
    123
  2. Bảng donhang chi tiết về đơn đặt hàng…
    1234

E muốn viết 1 trigger cho bảng donhang, khi update column “sl” trong bảng donhang thì column “soluongton”
trong bảng stock update theo, code của e:

CREATE TRIGGER xulydathang
ON dbo.donhang
for  UPDATE
as
BEGIN
    UPDATE STOCK
         SET soluongton =soluongton - (SELECT sl FROM donhang ) FROM Inserted,dbo.donhang
    WHERE Inserted.ordered=stock.id
END;

Khi em update:

UPDATE donhang SET sl=8 WHERE id_donhang=1921;

thì lại lỗi

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

Có ai chỉ lỗi của e mắc phải với được không…

Bạn hãy thử giả thích lại chỗ này xem

thông thường với những câu mà tính toán phức tạp, thì nên thêm ngoặc cho nó rõ ràng, thường là mình sẽ viết một câu như bên dưới, sau đó sửa phần trong ngoặc lại cho đúng

UPDATE STOCK
SET soluongton = soluongton - (tính toán ở trong này)
WHERE Inserted.ordered=stock.id
4 Likes

nếu mình chạy ko như vầy sẽ bị báo lỗi


Tức là ở câu WHERE Inserted.ordered=stock.id, nếu chạy ko như vầy nó ko hiểu inserted là cái gì nên phải thêm câu
FROM Inserted,dbo.donhang.
cái này mình cũng google thôi nên còn lủng cũng lắm…

SELECT sl FROM donhang 

bản thân câu query này không trả về 1 giá trị, mà có thể trả về nhiều record
việc bạn dùng một giá trị, để trừ cho một cái danh sách là đã sai rồi, câu trong ngoặc ra đến 10 dòng thì trừ cái nào? đó là lý do mình hỏi bạn muốn gì với phần trong ngoặc đó

SET soluongton =soluongton - (SELECT sl FROM donhang) 

bạn nên chủ động hơn trong việc code, không phải là cứ sửa đại và mong chờ code sẽ work sau khi sửa.
nếu bạn không giải thích được code của mình đang viết là cái gì, xử lý cái gì thì thua rồi (ở đây đang muốn nói từng dòng code, từng lệnh, dừng biểu thức mà bạn viết)

  1. Bạn đang viết sql cho cơ sở dữ liệu nào? mysql/mariadb/postgressql/sql server/oracle???
  2. bạn đang viết trigger cho thao tác gì?
  3. Inserted trong đó có ý nghĩa là gì?

thay vì cứ chỉnh sửa mà không có một định hướng nào thì bạn nên list ra các task mà bạn muốn thực hiện trong trigger đó, mà viết code cho các step của các task đó

4 Likes
  1. Mục đích ban đầu của mình là cập nhật ‘sl’ ở bảng stock mỗi khi có thay đổi ở bảng ‘donhang’.
    column ‘sl’ ở bảng stock sẽ cập nhật theo công thức:
    a). Có đơn hàng mới được thêm: stock.sl=stock.sl - (số lượng vừa mới đặt )
    b) Khách hủy đơn: stock.sl=stock.sl + (số lượng trong đơn khách mới hủy )

  2. Inserted là bảng ảo tự tạo ra khi trigger chạy, bảng ảo Inserted này thiết kế giống với bảng mà mình đang tạo trigger…
    Mỗi khi mình Insert vào bảng chính thì các record mới được insert đó nằm trong bảng Inserted này

Để cụ thể hơn mình tạo trigger demo

Bây giờ mình Insert thêm vào bảng đơn hàng…

Khi chạy câu Insert trên, trigger đã được gọi tới và xử lý, kết quả trên là bảng Inserted

Và để giải quyết khi bảng Inserted có nhiều record và code ko thể chạy mình dùng đến cursor

Run :


và stock đã update theo ý mình…
cảm ơn Bạn rất nhiều,

1 Like

Chúc mừng bạn đã giải quyết vấn đề.

Tuy nhiên thiết kế database như này không được thực tế cho lắm. Hoặc kể cả là bài tập mà thiết kế như này cũng sẽ tốn nhiều công sức hơn cho việc viết sql.
Nếu chỉ đơn thuần là bài tập và cho phép tự do trong việc thiết kế và truy vấn (chỉ có yêu cầu chứ không bắt buộc giải pháp phải như thế này như thế kia). Thì bạn chỉ cần join bảng là có thể tính ra được số lượng của mỗi sản phẩm ở thời điểm hiện tại. Hoặc có thể mở rộng database, 1 sản phẩm có thể nhập được nhiều lô hàng nhiều thời điểm, như vậy với những yêu cầu cao hơn kiểu “report số lượng tồn kho tại thời điểm nào đó” thì cũng sẽ tính toán được
Anyway, bài tập đã giải được thì việc mở rộng ý tưởng hay tham khảm thêm chỉ là optional

Hy vọng bạn không cảm thấy phiền vì những comment của mình.

4 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?