Sql 如何使用多个值更新列
我是PLSQL的新手,我想知道如何用多个值更新列。例如,假设我有一个名为books的表,它有一个书名和书价,在开始时,我只有书“C#”的价格300。更新之后,我需要将300和400作为“C#”一书的价格Sql 如何使用多个值更新列,sql,oracle,Sql,Oracle,我是PLSQL的新手,我想知道如何用多个值更新列。例如,假设我有一个名为books的表,它有一个书名和书价,在开始时,我只有书“C#”的价格300。更新之后,我需要将300和400作为“C#”一书的价格 在同一列中使用多个值并用某些特定字符分隔,这绝不是一个好主意。该表应该规范化,或者我们可以添加一个新的可空列,如UpdatedPrice,并使用它,如: ALTER TABLE BOOK ADD COLUMN UpdatedPrice int GO UPDATE BOOK SET Update
在同一列中使用多个值并用某些特定字符分隔,这绝不是一个好主意。该表应该规范化,或者我们可以添加一个新的可空列,如UpdatedPrice,并使用它,如:
ALTER TABLE BOOK
ADD COLUMN UpdatedPrice int
GO
UPDATE BOOK
SET UpdatedPrice = 400
WHERE Book_Name = 'C#'
这样,您可以同时获得两种价格。在代码中,当UpdatedPrice为空时使用Price,否则使用UpdatedPrice,一切都会好起来。创建一个触发器来保持以前的价格
CREATE OR REPLACE TRIGGER trig_book
BEFORE UPDATE OF price
ON book
FOR EACH ROW
BEGIN
:new.price := :old.price || ',' || :new.price;
END;
这只是创建存储过程的基本方法,您可以通过在更新后捕获错误代码来改进它。在oracle中缝合字符串的命令是| |
Create or Replace Procedure upd_Book_Price (in_book_name varchar(10),
in_newprice varchar(10));
IS
BEGIN
Update Book
Set Price = Price || ',' || in_newprice
Where Book_Name = in_book_name;
Commit;
End;
我建议另一个-标准化-选项(我看到你问那会是什么?。有很多来源,这是怎么说的),一个包含这些书的所有价格的子表 虽然你可以把两个(或更多的价格)放在一列中,但相信我们——这是一个糟糕的选择 考虑使用类似的方法:
SQL> create table book
2 (isbn varchar2(13) primary key,
3 name varchar2(20) not null
4 );
Table created.
SQL> create table price
2 (id number primary key,
3 isbn varchar2(13) constraint fk_pr_boo references book (isbn),
4 date_from date not null,
5 price number
6 );
Table created.
SQL>
SQL> insert all
2 into book (isbn, name) values ('1-1234-124', 'C#')
3 into book (isbn, name) values ('9-1244-332', 'C++')
4 --
5 into price (id, isbn, date_From, price) values (1, '1-1234-124', date '2018-01-01', 300)
6 into price (id, isbn, date_From, price) values (2, '1-1234-124', date '2018-03-20', 400)
7 select * From dual;
4 rows created.
SQL>
SQL> select b.isbn, b.name, p.date_from, p.price
2 from book b left join price p on p.isbn = b.isbn
3 order by b.isbn, p.date_from;
ISBN NAME DATE_FROM PRICE
------------- -------------------- ---------- ----------
1-1234-124 C# 01.01.2018 300
1-1234-124 C# 20.03.2018 400
9-1244-332 C++
SQL>
Book_Name| Price
---------|--------
C# | ,400
正如其他人已经提到的,在一列中共享多个值是不好的做法。如果您确实需要一种产品(书籍)的多种价格,有几种可能的选择: 制作两张表格: 表1: 这样,一个产品可以有多个价格,只需将产品名称保存在一行,而不是多行 第二种方法是使用关系表:
create table products
( id number(5),
name VARCHAR2(20 CHAR)
);
/
create table prices
( id number(5),
value number(6,2),
product_id number(5)
)
/
create table product_price
( product_id number(5),
price_id number(5),
FOREIGN KEY (product_id)
REFERENCES products(id) NOT NULL,
FOREIGN KEY (price_id)
REFERENCES prices(id) NOT NULL
)
/
insert into products values(1, 'C#');
insert into products values(1, 'C++');
insert into prices values(1, 300);
insert into prices values(2, 400);
insert into prices values(3, 700);
insert into product_price values(1, 1);
insert into product_price values(1, 2);
insert into product_price values(2, 3);
在一列中存储多个值总是一个坏主意,因为这会使读取数据变得非常困难,并带来各种其他问题(如何更新包含的4个值中的一个值?)
始终尝试在数据库中只保存每个值一次(即产品名称“C”)。并寻找最适合您的解决方案的方法。如果你总是得到只适合一种产品的多个价格,我会选择第一种方法,有两个表。如果有多个价格匹配多个产品,我会选择关系表
如果您只想在更新列之前保存上一个价格,请编写触发器将其保存到日志表:
create trigger tu_tablename --tu = triggerUpdate
before insert on tablename
for each row
begin
--writes the values before the insert to the log table
insert into logTable values (:old.name, :old.price, sysdate);
--logTable has columns product_name, old_price_value and date_change
end;
/
(请原谅可能出现的语法错误,将其视为挑战)数据库表中的列有一个数据类型,并且应该有一个值。尽管如果你真的想这样做,你可以在更新时使用连接,像这样添加到任何已经存在的字符中(不需要PL/SQL,只需要普通SQL): 顺便说一句,如果一本书没有价格,而你做了这个更新,它最终会变成这样:
SQL> create table book
2 (isbn varchar2(13) primary key,
3 name varchar2(20) not null
4 );
Table created.
SQL> create table price
2 (id number primary key,
3 isbn varchar2(13) constraint fk_pr_boo references book (isbn),
4 date_from date not null,
5 price number
6 );
Table created.
SQL>
SQL> insert all
2 into book (isbn, name) values ('1-1234-124', 'C#')
3 into book (isbn, name) values ('9-1244-332', 'C++')
4 --
5 into price (id, isbn, date_From, price) values (1, '1-1234-124', date '2018-01-01', 300)
6 into price (id, isbn, date_From, price) values (2, '1-1234-124', date '2018-03-20', 400)
7 select * From dual;
4 rows created.
SQL>
SQL> select b.isbn, b.name, p.date_from, p.price
2 from book b left join price p on p.isbn = b.isbn
3 order by b.isbn, p.date_from;
ISBN NAME DATE_FROM PRICE
------------- -------------------- ---------- ----------
1-1234-124 C# 01.01.2018 300
1-1234-124 C# 20.03.2018 400
9-1244-332 C++
SQL>
Book_Name| Price
---------|--------
C# | ,400
要防止出现这种情况,请添加一个大小写,以便在其中已有其他值时不包含逗号:
UPDATE Book set Price =
CASE WHEN Price IS NOT NULL
THEN Price || ', '|| '400'
else '400'
end
where Book_Name = 'C#' ;
然而,这种设计不是很好。这意味着在字符数据类型的列中,您已经放置了隐藏在其中的数字
最好是有多个列:
Book_Name| Price1 | Price2
---------|----------|--------
C# | 300 | 400
C++ | 500 | 600
Java | 700 | 800
以上是罚款,如果你知道不同的价格,你将有多少。这取决于您试图解决的问题,取决于业务逻辑。但是,如果您不知道可能的价格的最大数量,那么为每本书设置一个二级价格表是有意义的(您需要为每本书设置一个不同的ID,根据该ID,另一个表将有一个其所有价格的列表),或者可以这样更改现有表:
Book_Name| Prices
---------|----------
C# | 300
C# | 400
C++ | 500
C++ | 600
Java | 700
Java | 800
在这种情况下,您不必进行更新,而是每次插入新行:
INSERT INTO Book (Book_Name, Price) VALUES ( 'C#', 400) ;
INSERT INTO Book (Book_Name, Price) VALUES ( 'C++', 600) ;
INSERT INTO Book (Book_Name, Price) VALUES ( 'Java', 800) ;
@kc2018这行不通,因为我需要更新我已经拥有的varray的price列中的值。你应该规范化你的table@Triple3XH阅读一些数据库设计书籍。你的设计会带来灾难。最好现在就修改你的设计,而不是以后。他说的triple3xh是指你的书表应该有Id、标题、作者、主题等信息。如果你的书的属性可以是0多个值,你应该有一个相关的查找表,例如“BookPrices”和Id、book\u Id、Price列,该书的每个价格可能都有一个条目。此表将替换book表中逗号分隔的列。请勿在一列中存储多个逗号分隔的值。这会给你带来很多问题,这只是一个开始。对于所有的答案,我知道这不是一个好的做法,但这是任务的要求
INSERT INTO Book (Book_Name, Price) VALUES ( 'C#', 400) ;
INSERT INTO Book (Book_Name, Price) VALUES ( 'C++', 600) ;
INSERT INTO Book (Book_Name, Price) VALUES ( 'Java', 800) ;