这几天开发同学反映了一个问题,有一个Java写的夜维程序,用于每天定时删除历史过期数据,3月10日之前经过了内测,但这两天再次执行的时候,有一条SQL语句一直报ORA-01752的错误,由于近期做过一次开发库的迁移,从一个机房搬迁至另一个机房,而且开发同学确认这期间未变代码逻辑,所以怀疑是否和数据迁移有关,这个错误被测试同学提为了bug,卡在版本测试中,有可能造成进度延误,所以属于比较紧急的问题。

再来捋一下这问题的信息,
(1).报错的SQL

delete FROM (select * from TBL_A a inner join TBL_B b on a.a_id = b.id inner join TBL_C c on b.b_a = c.c_a and b.b_b = c.c_b where c.c_date <= trunc(sysdate)-1) where ROWNUM <= 10;

(2).3月10日之前这条SQL可以执行,现在再执行就会报错,
ORA-01752: cannot delete from view without exactly one key-preserved table
(3).3月10日左右做过数据迁移,exp/imp导出导入数据。

首先,我们看下ORA-01752错误是什么意思,

01752, 00000, “cannot delete from view without exactly one
key-preserved table”
// *Cause: The deleted table had
// - no key-preserved tables,
// - more than one key-preserved table, or
// - the key-preserved table was an unmerged view.
// *Action: Redefine the view or delete it from the underlying base tables.

含义是不能从一个没有明确key-preserved表的视图中执行delete操作。
原因有三个,没有key-preserved表,多于一张key-preserved表,或者key-preserved表是一个非合并视图。
解决方法是重新定义视图,或者从基表中执行delete操作。

这解释比较懵,什么叫key-preserved表?为什么执行delete语句删除这些select多表关联形成的view需要有一个key-preserved表?

看看Oracle官方文档对key-preserved表是如何定义的,
(http://docs.oracle.com/cd/E11882_01/server.112/e25494/views.htm#i1006318)

key-preserved表是理解限制修改连接视图join view的基础。如果一张表的主键/唯一键是join连接结果集的主键/唯一键,那么这张表就叫做key-preserved表。因此key-preserved表的主键/唯一键在join连接过程中会被一直保留。

并非这张表的主键/唯一键一定要出现在select子句中,但若其出现在join连接的结果集中,则必须要满足作为这个结果集主键/唯一键的要求。

表的key-preserving属性不依赖于表中的实际数据。例如,如果emp表最多有一个雇员位于每一个部门,那么deptno字段在emp和dept的连接结果集中将会是一个唯一值,但是不会因为若存在这样的数据就定义dept是一张key-preserved表。

在这张视图中,emp是一张key-preserved表,因为empno是emp表的主键,也可以看出其是join连接结果集的主键。dept不是一张key-preserved表,因为尽管deptno是dept表中的主键,但他不是join连接结果集中的主键。

(http://docs.oracle.com/cd/E11882_01/server.112/e40540/schemaob.htm#CNCPT1514)

如果定义视图的FROM子句中有多张表或视图,那么这张视图就叫做join view连接视图。

可更新的join view连接视图,也叫做可修改的join view连接视图,包括两张或更多张基表或视图,允许执行DML操作。可更新视图的FROM子句中会有SELECT语句包含多张表,并且不会有WITH READ ONLY子句限制。

为了继承可更新,视图必须满足一些标准。例如,一条通用的规则就是,INSERT、UPDATE或DELETE操作一次只能影响一张基表。

USER_UPDATABLE_COLUMNS数据字典会返回上面创建的这张join view连接视图是可更新的,join view连接视图中所有可更新的列必须映射至key-preserved表的列上。key-preserved表是每行数据最多在结果集中出现一次的基表。department_id是departments表的主键,所以employees表中每行数据在结果集中最多只会出现一次,因此employees表是一张key-preserved表。departments表不是key-preserved表,因为其每行数据可能多次出现于结果集中。

简单用一个实验说明下,
实验一-假设emp表有以下数据,

employee_id, department_id
1,1
2,1
3,2

假设dept表有以下数据,且department_name字段不是主键,

department_id,department_name
1,'a'
1,'b'
2,'a'

那么,emp和dept组成的视图包含如下记录,

employee_id,department_id,department_name
1,1,'a'
1,1,'b'
2,1,'a'
2,1,'b'
3,2,'a'

可以看出emp表每条数据是可能重复的,因此emp表不是key-preserved表。

实验二-假设emp表有如下数据,

employee_id, department_id
1,1
2,1
3,2

假设dept表有如下数据,且department_name字段是主键,

department_id,department_name
1,'a'
2,'a'

那么,emp和dept表组成的视图有如下记录,

employee_id,department_id,department_name
1,1,'a'
2,1,'a'
3,2,'a'

可以看出emp表每条数据是不会重复的,因此emp表是一张key-preserved表。

(http://docs.oracle.com/cd/E11882_01/server.112/e41084/statements_8004.htm#SQLRF01504)

A key-preserved table is one for which every primary key or unique key value in the base table is also unique in the join view.

If you want a join view to be updatable, then all of the following
conditions must be true:
● The DML statement must affect only one table underlying the join.
● For an INSERT statement, the view must not be created WITH CHECK OPTION, and all columns into which values are inserted must come from a key-preserved table. A key-preserved table is one for which every primary key or unique key value in the base table is also unique in the join view.
● For an UPDATE statement, the view must not be created WITH CHECK OPTION, and all columns updated must be extracted from a key-preserved table.
● For a DELETE statement, if the join results in more than one key-preserved table, then Oracle Database deletes from the first table named in the FROM clause, whether or not the view was created WITH CHECK OPTION.

DELETE语句,如果join结果集中有多张key-preserved表,则Oracle会删除FROM子句第一张表,不管其视图是否用WITH CHECK OPTION创建。

DML语句必须仅会影响一张基表。

从以上文档,总结下主要观点,多表关联的一个updatable join view视图,如果语法上允许删除,则Oracle只会删除其中一张基表,这张表就是key-preserved表,如果一张表的主键/唯一键是updatable join view视图连接结果集的主键/唯一键,那么这张表就叫做key-preserved表。

用实验来说明,

SQL> create table t_a (x number primary key);
Table created.SQL> create table t_b (x number primary key);
Table created.SQL> insert into t_a values(1);
1 row created.SQL> insert into t_a values(2);
1 row created.SQL> insert into t_b values(1);
1 row created.SQL> commit;
Commit complete.SQL> select * from t_a;X
----------12SQL> select * from t_b;X
----------1SQL> delete from2  (select a.x, b.x from t_a a, t_b b where a.x = b.x);
1 row deleted.SQL> select * from t_a; X
----------2SQL> select * from t_b;X
----------1

此时可以执行删除语句,删除的是第一张表t_a的记录。

SQL> rollback;
Rollback complete.SQL> delete from2  (select a.x, b.x from t_b b, t_a a where a.x = b.x);
1 row deleted.SQL> select * from t_a;X
----------12SQL> select * from t_b;
no rows selected

此时删除语句可以执行,删除的是第一张表t_b的记录。

以上实验说明了,
(1).不像ORA-01752错误提示中所说的,“more than one key-preserved table”会导致这种错误,delete可以删除两张不同的key-preserved表。
(2).delete会删除select … from子句跟着的第一张表,如上例中,t_a或t_b谁是第一张表,则谁会被删除。

实验和ORA-01752的描述自相矛盾了,Tom其实在这篇文章中提到了这个问题(https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:184812348071),指出这是从9i之后的DELETE行为,为此记录了bug,

that is the behavior of DELETE since version 9i, I filed a documentation bug against that a while ago and it is updated in the current doc set:
http://docs.oracle.com/docs/cd/E11882_01/server.112/e10595/views001.htm#ADMIN11786

这个链接已经失效了,但通过检索,其来源就是《Database Administrator’s Guide》的DELETE Statements and Join Views章节。

再看11.2、12.1和12.2三个版本这一章节的说明,叙述上略不同。
11.2
http://docs.oracle.com/cd/E11882_01/server.112/e25494/views.htm#ADMIN11781
You can delete from a join view provided there is one and only one key-preserved table in the join.

12.1
http://docs.oracle.com/database/121/ADMIN/views.htm#ADMIN-GUID-367FAA9B-269C-41AD-A429-631D144CF36F
For most join views, a delete is successful only if there is one and only one key-preserved table in the join.

12.2
http://docs.oracle.com/database/122/ADMIN/managing-views-sequences-and-synonyms.htm#ADMIN11781
For most join views, a delete is successful only if there is one and only one key-preserved table in the join

11.2指出join连接中有且仅有一张key-preserved表,才能执行连接视图的delete删除。

12.1和12.2叙述相同,对于大多数连接视图,join连接中有且仅有一张key-preserved表,才能执行连接视图的delete删除。

如下是11.2的原文,

HuangYong大师的一段解释很形象,

“Indeed the documentation is not complete. It does talk about two key-preserved tables. There’s a Note box saying “If the DELETE statement uses the same column in its WHERE clause that was used to create the view as a join condition, then the delete operation can be successful when there are different key-preserved tables in the join.”

But that doesn’t explain your case, which I still have trouble completely understanding. Here’s my thinking. The join condition in the in-line view, “a.a_id = b.id”, causes tbl_b to act as the parent and tbl_a as a child because tbl_b.id is PK. I know you didn’t explicitly define the foreign key on tbl_a, so I say “act as”. Then you have the join conditions “b.b_a = c.c_a and b.b_b = c.c_b”. But these don’t establish a parent-child relation between tbl_b and tbl_c because there’s no key involved. As soon as you create the unique key on (c_a,c_b) of tbl_c, tbl_c acts like the parent and tbl_b the child. Now the relationship among all 3 tables are clear: tbl_c acts like the parent of tbl_b, which acts like the parent of tbl_a. The bottom table (tbl_a) is the most detailed and is the key-preserved table.“

这个bug则记录了此问题,“Bug 24921723 : DOCUMENTATION BUG - DELETE STATEMENTS AND JOIN VIEWS”

bug进一步说明了这个问题,文档中应该反映出这种行为。

For the first point above, it is not true that you can delete from a join view provided there is one and only one key-preserved table in the join. The delete will work even though there are two different key preserved tables in the join. we can see that the delete is working even though there are two different key-preserved tables and its not necessarily same table should be repeated. The documentation should be changed to reflect this behavior.

Again as said in point 1) this should be changed to reflect that the delete table operates on the first table in the list and the tables in the from list doesn’t necessarily to be same key-preserved table and it can be different tables. If the DELETE statement uses the same column in its WHERE clause that was used to create the view as a join condition, then the delete operation can be successful when there are different key-preserved tables in the join. In this case, the DELETE statement operates on the first table in the FROM list, and the tables in the FROM list can be different from the tables in the WHERE clause.

这个bug在11.2.0.3提出,12.1.0.2修复,就是在文档中增加了“For most join views”这一句,说明是有例外。

既然上面介绍了什么是ORA-01752错误,什么是key-preserved表,接下来我们模拟下开始的问题,

(1) 创建三张测试表,

SQL> create table tbl_a (id number primary key, a_id number);
Table created.SQL> create table tbl_b (id number primary key, b_a varchar2(1), b_b varchar2(1));
Table created.SQL> create table tbl_c (id number primary key, c_a varchar2(1), c_b varchar2(1), insert_time timestamp);
Table created.

(2) 创建模拟数据,

SQL> insert into tbl_a values(1, 1);
1 row created.SQL> insert into tbl_a values(2, 2);
1 row created.SQL> insert into tbl_b values(1, 'a', 'a');
1 row created.SQL> insert into tbl_b values(2, 'b', 'b');
1 row created.SQL> insert into tbl_b values(3, 'c', 'c');
1 row created.SQL> insert into tbl_c values(1, 'a', 'a', sysdate-1);
1 row created.SQL> insert into tbl_c values(2, 'b', 'b', sysdate);
1 row created.SQL> insert into tbl_c values(3, 'c', 'c', sysdate);
1 row created.SQL> commit;
Commit complete.SQL> select * from tbl_a;ID       A_ID
---------- ----------1          12          2SQL> select * from tbl_b;ID B B
---------- - -1 a a2 b b3 c cSQL> select * from tbl_c;ID C C INSERT_TIME
---------- - - -----------------------------------------1 a a 27-MAR-17 05.11.58.000000 PM2 b b 28-MAR-17 05.12.11.000000 PM3 c c 28-MAR-17 05.12.27.000000 PM

单独执行select … from子句,可以知道会返回一条记录,

SQL> select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate);ID       A_ID         ID B B         ID C C INSERT_TIME
---------- ---------- ---------- - - ---------- - - ------------
1          1          1 a a          1 a a 27-MAR-17 05.11.58.000000 PM

执行DELETE语句会报错ORA-01752,

SQL> delete from2  (select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c3  on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate))4  where rownum <=2;
(select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c
*
ERROR at line 2:
ORA-01752: cannot delete from view without exactly one key-preserved table

此时为表TBL_B增加唯一约束,执行DELETE语句,继续报错,

SQL> alter table tbl_b add constraint unique_tbl_b_01 unique (b_a, b_b);
Table altered.SQL> delete from2  (select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c3  on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate))4  where rownum <=2;
(select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c
*
ERROR at line 2:
ORA-01752: cannot delete from view without exactly one key-preserved table

此时为表TBL_C增加唯一约束,执行DELETE语句,可正常删除,并且可知删除的是表TBL_A数据,

SQL> alter table tbl_c add constraint unique_tbl_c_01 unique (c_a, c_b);
Table altered.SQL> delete from
(select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c
on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate))
where rownum <=2;
1 row deleted.SQL> select * from tbl_a;ID       A_ID
---------- ----------2          2SQL> select * from tbl_b;ID B B
---------- - -1 a a2 b b3 c cSQL> select * from tbl_c;ID C C INSERT_TIME
---------- - - ---------------------------------------------------------------------------1 a a 27-MAR-17 05.11.58.000000 PM2 b b 28-MAR-17 05.12.11.000000 PM3 c c 28-MAR-17 05.12.27.000000 PM

此时为表TBL_C增加唯一约束,不同的是唯一约束包含了id字段,执行DELETE语句(未包含id字段)报错ORA-01752,说明不能确定key-preserved表,

SQL> alter table tbl_c add constraint unique_tbl_c_01 unique (c_a, c_b, id);
Table altered.SQL> delete from
(select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c
on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate))
where rownum <=2;
(select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c
*
ERROR at line 2:
ORA-01752: cannot delete from view without exactly one key-preserved table

换一种方式,创建和上面DELETE相同语义的视图,

SQL> create view v_abc as select a.a_id, b.id, b.b_a, b.b_b, c.c_a, c.c_b, c.insert_time from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate);
View created.

从user_updatable_columns视图中可以看出,原始视图所有列均不可增删改,

SQL> select * from user_updatable_columns where table_name='V_ABC';
OWNER                          TABLE_NAME COLUMN_NAME                    UPD INS DEL
BISAL                          V_ABC      A_ID                           NO  NO  NO
BISAL                          V_ABC      ID                             NO  NO  NO
BISAL                          V_ABC      B_A                            NO  NO  NO
BISAL                          V_ABC      B_B                            NO  NO  NO
BISAL                          V_ABC      C_A                            NO  NO  NO
BISAL                          V_ABC      C_B                            NO  NO  NO
BISAL                          V_ABC      INSERT_TIME                    NO  NO  NO
7 rows selected.

增加TBL_C唯一约束,创建视图,

SQL> alter table tbl_c drop constraint unique_tbl_c_01;
Table altered.SQL> alter table tbl_c add constraint unique_tbl_c_01 unique(c_a, c_b);
Table altered.SQL> create or replace view v_abc as select a.a_id, b.id, b.b_a, b.b_b, c.c_a, c.c_b, c.insert_time from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate);
View created.

此时user_updatable_columns视图中显示TBL_A表的a_id字段允许增删改了,

SQL> select * from user_updatable_columns where table_name='V_ABC';
OWNER                          TABLE_NAME COLUMN_NAME                    UPD INS DEL
BISAL                          V_ABC      A_ID                           YES YES YES
BISAL                          V_ABC      ID                             NO  NO  NO
BISAL                          V_ABC      B_A                            NO  NO  NO
BISAL                          V_ABC      B_B                            NO  NO  NO
BISAL                          V_ABC      C_A                            NO  NO  NO
BISAL                          V_ABC      C_B                            NO  NO  NO
BISAL                          V_ABC      INSERT_TIME                    NO  NO  NO
7 rows selected.

通过以上实验,可以推测出这条DELETE语句是否执行成功,取决于TBL_B和TBL_C表是否有主键或者唯一键,进而取决于要删除的TBL_A表记录是否可以唯一确定结果集中的记录,是否是key-preserved表。

我们对开发库的每次变更,都是使用自己开发的一套数据库变更工具执行的,会自动记录变更历史,而且变更的细节,结合Confluence会有记录,TBL_C表3月10日之前,曾经创建过一个唯一约束,字段是(C_A, C_B),3月10日,开发提出了一次变更需求,向这个唯一约束中增加了另外一个字段C_C,此时(C_A, C_B, C_C)可以唯一确定一条记录,(C_A, C_B)不能唯一确定一条记录。

举个例子,

SQL> select * from tbl_a;ID       A_ID1          12          2SQL> select * from tbl_b;ID B B1 a a2 b b3 c cSQL> select * from tbl_c;ID C C INSERT_TIME1 a a 27-MAR-17 06.46.09.000000 PM2 b b 27-MAR-17 06.46.09.000000 PM3 c c 27-MAR-17 06.46.09.000000 PM4 a a 27-MAR-17 06.46.09.000000 PM5 a a 27-MAR-17 06.46.09.000000 PMSQL> select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate);
ID       A_ID         ID B B         ID C C INSERT_TIME
1          1          1 a a          1 a a 27-MAR-17 06.46.09.000000 PM
2          2          2 b b          2 b b 27-MAR-17 06.46.09.000000 PM
1          1          1 a a          4 a a 27-MAR-17 06.46.09.000000 PM
1          1          1 a a          5 a a 27-MAR-17 06.46.09.000000 PMSQL> insert into tbl_a values(3, 1);SQL> select * from tbl_a a inner join tbl_b b on a.a_id = b.id inner join tbl_c c on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate);
ID       A_ID         ID B B         ID C C INSERT_TIME
1          1          1 a a          1 a a 27-MAR-17 06.46.09.000000 PM
3          1          1 a a          1 a a 27-MAR-17 06.46.09.000000 PM
2          2          2 b b          2 b b 27-MAR-17 06.46.09.000000 PM
1          1          1 a a          4 a a 27-MAR-17 06.46.09.000000 PM
3          1          1 a a          4 a a 27-MAR-17 06.46.09.000000 PM
1          1          1 a a          5 a a 27-MAR-17 06.46.09.000000 PM
3          1          1 a a          5 a a 27-MAR-17 06.46.09.000000 PM
7 rows selected.

此时不能根据TBL_A、TBL_B或TBL_C的主键来确定join连接结果集的主键,因此无key-preserved表,Oracle不能明确需要删除的基表,所以报错ORA-01752。

解决方案
(1). 为了删除TBL_A的数据,需要让其成为key-preserved表,因此除了TBL_B有主键限定唯一值,还需要让TBL_C的条件限定唯一值,例如可以再次修改唯一约束为(C_A,C_B)这两个字段,但这可能和业务需求不一致。
(2). 改写SQL,
delete from
(select * from tbl_a a where a.a_id in (select b.id from tbl_b b inner join tbl_c c
on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate))) where rownum <= 2;
或者
delete from
(select * from tbl_a a where exists (select 1 from t_b b inner join tbl_c c
on b.b_a = c.c_a and b.b_b = c.c_b where c.insert_time <= trunc(sysdate))) where rownum <= 2;
至于使用IN还是EXISTS,需要结合子表可能返回的结果集记录大小再选择。

然而,开发同学提出了一种建议,

请将约束改为(C_A, C_B, C_C),SQL则改为
delete FROM (select * from TBL_A a inner join TBL_B b on a.a_id = b.id inner join TBL_C c on b.b_a = c.c_a and b.b_b = c.c_b and c.c_c is null where c.c_date <= trunc(sysdate)-1) where ROWNUM <= 10;
其中c_c列允许为空。

这条SQL报错ORA-01752,原因就是因为null是一个特殊的值,我们使用条件的时候,会用is null/is not null,不会用=null,换句话说,null和null不是等价的,因此允许这样的数据,

create table tbl (a varchar2(1), b varchar2(1), c varchar2(1));
insert into tbl values('a', 'b', '');
insert into tbl values('a', 'b', '');
select * from tbl;
a b
a b

这种写法符合ORA-01752错误的范围。

总结
(1) ORA-01752错误从描述看会有些晦涩,主要是能理解key-preserved表的含义,才能逐步理解错误的原因。
(2) Oracle官方文档中任何一处细节的变化,可能蕴含着一些改进,只看文档是不能理解的,唯有实际操作才能理解含义。
(3) 认为对的就要坚持,即使是文档,辩证地看待问题。

要谢谢lastwinner和HuangYong两位大师的指点迷津,透过现象看本质,是这次学习到的一点经验。

欢迎关注我的个人微信公众号:bisal的个人杂货铺

从ORA-01752的错误,透过现象看本质相关推荐

  1. 透过现象看本质:喧闹的中国电子商务

    吴军先生做<透过现象看本质:喧闹的中国电子商务>主题演讲,剖析中国电子商务行业的现状和格局,预测未来行业趋势,并针对传统企业.中小企业的具体情况,给出一些策略上的建议. 以下是吴军先生的现 ...

  2. 透过现象看本质: 常见的前端架构风格和案例

    所谓软件架构风格,是指描述某个特定应用领域中系统组织方式的惯用模式.架构风格定义一个词汇表和一组约束,词汇表中包含一些组件及连接器,约束则指出系统如何将构建和连接器组合起来.软件架构风格反映了领域中众 ...

  3. 传统金融PK互联网 必须透过现象看本质

    传统金融PK互联网 必须透过现象看本质 面对越来越热的互联网金融,传统金融业内人士与互联网的发生激烈了冲突,中国近期的经济疲软似乎也变成了互联网金融的原罪之一,但事实真是如此吗? width=&quo ...

  4. 软件架构设计案例_透过现象看本质:常见的前端架构风格和案例

    所谓软件架构风格,是指描述某个特定应用领域中系统组织方式的惯用模式.架构风格定义一个词汇表和一组约束,词汇表中包含一些组件及连接器,约束则指出系统如何将构建和连接器组合起来.软件架构风格反映了领域中众 ...

  5. 透过现象看本质,如何针对用户做好需求分析

    对于刚入门的产品经理而言,很容易出现设计出来的产品功能不达用户预期的情况.这里面一部分原因是由于需求分析没做到位,忽略了事情背后的本质.那么下面我们看看如何做好需求分析. 透过现象看本质 我们只有透过 ...

  6. 大道至简之四:透过现象看本质

    大道至简:透过现象看本质 --投资总结之四         时寒冰 研究趋势是一件充满挑战和趣味的事情.     我深信,很多现象是有规律可循的.     但是,对于趋势的判断尤其提前做出的判断,短期 ...

  7. 大道至简:透过现象看本质

    大道至简:透过现象看本质 --投资总结之四         时寒冰 研究趋势是一件充满挑战和趣味的事情.     我深信,很多现象是有规律可循的.     但是,对于趋势的判断尤其提前做出的判断,短期 ...

  8. 黄金思维圈,养成透过现象看本质的能力

    loonggg 读完需要 3 分钟 速读仅需 1 分钟 大家好,我是你们的校长. 今天我想给大家聊一聊关于思考,关于黄金思维圈的问题.如果你有了黄金思维圈的思维,带着目的去做一件事情,不仅仅会养成透过 ...

  9. ChatGPT爆火背后的原因:透过现象看本质

    ChatGPT爆火背后的原因:透过现象看本质 随着人工智能技术的快速发展,我们已经在许多领域看到了AI的身影.在最近的一段时间里,ChatGPT成为了一个引起广泛关注的现象.ChatGPT以其强大的自 ...

最新文章

  1. Ubuntu16下安装kaldi(使用物理主机)
  2. pinctrl 和 gpio 子系统
  3. Linux 文件系统引起的云盘文件系统异常导致 MySQL 数据页损坏事故恢复复盘
  4. python plot 坐标轴范围_Python-Matplotlib 15 坐标轴范围
  5. 关于jsp页面是放在webroot目录下和web-inf下优缺点
  6. 课堂练习之谁是水王(一)
  7. 动态规划算法-05KSum问题
  8. 【精华总结】全文4000字、20个案例详解Pandas当中的数据统计分析与排序
  9. 【转】使用python进行多线程编程
  10. 158. class, static, self, parent
  11. 《软件评测师教程》学习笔记-第一章:软件测试概述
  12. 2020年尾矿考试技巧及尾矿考试平台
  13. validateNewTexture:89: failed assertion `BytesPerRow of a buffer-backed texture with pixelFormat
  14. ffmpeg重采样中swr_convert和swr_get_out_samples的用法
  15. 悟空 mobile.php,悟空crm系统pc+手机端PHPJAVA源码授权永久使用
  16. 使用 AppFuse 的七个理由(中英文两版)
  17. 时间轴-新年倒计时(实操java)
  18. Java8 IF ELSE IF 优化
  19. 7个秘诀,带你由数据分析师成长为数据科学家
  20. Android USB识别开发

热门文章

  1. 单位的消防工作有哪些,怎么干?
  2. 扫地机器人的清扫路径规划
  3. 利用Thumbnails 根据坐标裁剪图片
  4. 百望云亮相Inno China中国产业创新大会 赋能金融数据智能创新
  5. 技术债:HTTP/HTTPS
  6. proxifier注意事项
  7. 关于国外网站下载速度比较慢的解决办法
  8. Dynamo_在Revit参数间复制数据
  9. 百度大脑EasyDL专业版重磅升级 预置网络更丰富,开发更灵活
  10. 2021年9月云主机性能评测报告