• 关于 子查询-exists子查询 的搜索结果

回答

使用不存在: SELECT t.[CUSTOMER_ID], t.[PROPERTY_NAME], t.[LOCATION_CODE], t.[RESERVATION_DATE] FROM tablename AS t WHERE NOT EXISTS ( SELECT 1 FROM tablename WHERE [PROPERTY_NAME] = t.[PROPERTY_NAME] AND [RESERVATION_DATE] > t.[RESERVATION_DATE] ) 或在WHERE子句中使用子查询返回最新日期: SELECT t.[CUSTOMER_ID], t.[PROPERTY_NAME], t.[LOCATION_CODE], t.[RESERVATION_DATE] FROM tablename AS t WHERE t.[RESERVATION_DATE] = ( SELECT MAX([RESERVATION_DATE]) FROM tablename WHERE [PROPERTY_NAME] = t.[PROPERTY_NAME] ) 参见演示。 结果: > CUSTOMER_ID | PROPERTY_NAME | LOCATION_CODE | RESERVATION_DATE > ----------: | :------------ | :------------ | :------------------ > 1256 | c | c5 | 20/12/2019 > 1212 | b | B5 | 22/12/2019 > 1236 | a | A5 | 18/12/2019

祖安文状元 2020-01-05 14:05:40 0 浏览量 回答数 0

问题

MPP计算引擎 SELECT语法是什么?

nicenelly 2019-12-01 21:25:30 1617 浏览量 回答数 0

回答

如果将日期条件放在JOIN子句中,则无需任何子查询即可完成此操作。 以下是我在MySQL 5.0上测试过的代码。 SELECT m.name, COALESCE(SUM(oi.quantity), 0) AS count FROM menu_items AS m LEFT OUTER JOIN ( order_items AS oi JOIN orders AS o ON (o.id = oi.order_id) ) ON (m.id = oi.menu_item_id AND o.date BETWEEN '2008-11-01' AND '2008-11-30') GROUP BY m.id; 输出: +--------+-------+ | name | count | +--------+-------+ | bread | 2 | | milk | 1 | | honey | 2 | | cheese | 0 | +--------+-------+ 这是MySQL风格的DDL和设置代码: DROP TABLE IF EXISTS menu_items; CREATE TABLE menu_items ( id INT PRIMARY KEY, name VARCHAR(10) ) TYPE=InnoDB; DROP TABLE IF EXISTS orders; CREATE TABLE orders ( id INT PRIMARY KEY, date DATE ) TYPE=InnoDB; DROP TABLE IF EXISTS order_items; CREATE TABLE order_items ( order_id INT, menu_item_id INT, quantity INT, PRIMARY KEY (order_id, menu_item_id), FOREIGN KEY (order_id) REFERENCES orders(id), FOREIGN KEY (menu_item_id) REFERENCES menu_items(id) ) TYPE=InnoDB; INSERT INTO menu_items VALUES (1, 'bread'), (2, 'milk'), (3, 'honey'), (4, 'cheese'); INSERT INTO orders VALUES (1, '2008-11-02'), (2, '2008-11-03'), (3, '2008-10-29'); INSERT INTO order_items VALUES (1, 1, 1), (1, 3, 1), (2, 1, 1), (2, 2, 1), (2, 3, 1), (3, 4, 10);

保持可爱mmm 2019-12-02 03:17:13 0 浏览量 回答数 0

新用户福利专场,云服务器ECS低至96.9元/年

新用户福利专场,云服务器ECS低至96.9元/年

问题

MPP计算引擎 SELECT语法是什么?

nicenelly 2019-12-01 21:10:51 1381 浏览量 回答数 0

回答

MySQL 8.0现在支持窗口功能,就像几乎所有流行的SQL实现一样。使用这种标准语法,我们可以编写每组最多n个查询: WITH ranked_messages AS ( SELECT m.*, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id DESC) AS rn FROM messages AS m ) SELECT * FROM ranked_messages WHERE rn = 1; 以下是我在2009年为此问题写的原始答案: 我这样写解决方案: SELECT m1.* FROM messages m1 LEFT JOIN messages m2 ON (m1.name = m2.name AND m1.id < m2.id) WHERE m2.id IS NULL; 关于性能,一种解决方案可能会更好,这取决于数据的性质。因此,您应该测试两个查询,并使用给定数据库性能最好的查询。 例如,我有一个StackOverflow August数据转储的副本。我将其用于基准测试。该Posts表中有1,114,357行。它在Macbook Pro 2.40GHz的MySQL 5.0.75上运行。 我将编写查询以查找给定用户ID(我的用户)的最新帖子。 首先在子查询中使用@Eric 所示的技术GROUP BY: SELECT p1.postid FROM Posts p1 INNER JOIN (SELECT pi.owneruserid, MAX(pi.postid) AS maxpostid FROM Posts pi GROUP BY pi.owneruserid) p2 ON (p1.postid = p2.maxpostid) WHERE p1.owneruserid = 20860; 1 row in set (1 min 17.89 sec) 甚至EXPLAIN分析也要花费超过16秒的时间: +----+-------------+------------+--------+----------------------------+-------------+---------+--------------+---------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+----------------------------+-------------+---------+--------------+---------+-------------+ | 1 | PRIMARY | | ALL | NULL | NULL | NULL | NULL | 76756 | | | 1 | PRIMARY | p1 | eq_ref | PRIMARY,PostId,OwnerUserId | PRIMARY | 8 | p2.maxpostid | 1 | Using where | | 2 | DERIVED | pi | index | NULL | OwnerUserId | 8 | NULL | 1151268 | Using index | +----+-------------+------------+--------+----------------------------+-------------+---------+--------------+---------+-------------+ 3 rows in set (16.09 sec) 现在用产生同样的查询结果我的技术有LEFT JOIN: SELECT p1.postid FROM Posts p1 LEFT JOIN posts p2 ON (p1.owneruserid = p2.owneruserid AND p1.postid < p2.postid) WHERE p2.postid IS NULL AND p1.owneruserid = 20860; 1 row in set (0.28 sec) 该EXPLAIN分析表明,这两个表都能够使用他们的指标: +----+-------------+-------+------+----------------------------+-------------+---------+-------+------+--------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+------+----------------------------+-------------+---------+-------+------+--------------------------------------+ | 1 | SIMPLE | p1 | ref | OwnerUserId | OwnerUserId | 8 | const | 1384 | Using index | | 1 | SIMPLE | p2 | ref | PRIMARY,PostId,OwnerUserId | OwnerUserId | 8 | const | 1384 | Using where; Using index; Not exists | +----+-------------+-------+------+----------------------------+-------------+---------+-------+------+--------------------------------------+ 2 rows in set (0.00 sec) 这是我的Posts桌子的DDL : CREATE TABLE posts ( PostId bigint(20) unsigned NOT NULL auto_increment, PostTypeId bigint(20) unsigned NOT NULL, AcceptedAnswerId bigint(20) unsigned default NULL, ParentId bigint(20) unsigned default NULL, CreationDate datetime NOT NULL, Score int(11) NOT NULL default '0', ViewCount int(11) NOT NULL default '0', Body text NOT NULL, OwnerUserId bigint(20) unsigned NOT NULL, OwnerDisplayName varchar(40) default NULL, LastEditorUserId bigint(20) unsigned default NULL, LastEditDate datetime default NULL, LastActivityDate datetime default NULL, Title varchar(250) NOT NULL default '', Tags varchar(150) NOT NULL default '', AnswerCount int(11) NOT NULL default '0', CommentCount int(11) NOT NULL default '0', FavoriteCount int(11) NOT NULL default '0', ClosedDate datetime default NULL, PRIMARY KEY (PostId), UNIQUE KEY PostId (PostId), KEY PostTypeId (PostTypeId), KEY AcceptedAnswerId (AcceptedAnswerId), KEY OwnerUserId (OwnerUserId), KEY LastEditorUserId (LastEditorUserId), KEY ParentId (ParentId), CONSTRAINT posts_ibfk_1 FOREIGN KEY (PostTypeId) REFERENCES posttypes (PostTypeId) ) ENGINE=InnoDB;

保持可爱mmm 2020-05-08 10:11:26 0 浏览量 回答数 0

问题

SQL 优化方法有哪些?

猫饭先生 2019-12-01 21:20:55 1044 浏览量 回答数 0

回答

有三种方法可以执行此类查询: LEFT JOIN / IS NULL: SELECT * FROM common LEFT JOIN table1 t1 ON t1.common_id = common.common_id WHERE t1.common_id IS NULL NOT EXISTS: SELECT * FROM common WHERE NOT EXISTS ( SELECT NULL FROM table1 t1 WHERE t1.common_id = common.common_id ) NOT IN: SELECT * FROM common WHERE common_id NOT IN ( SELECT common_id FROM table1 t1 ) 当table1.common_id不为空时,所有这些查询在语义上都是相同的。 当它可空时,NOT IN是不同,因为 IN(and, therefore, NOT IN) 当一个值与包含空值的列表中的任何内容不匹配时,返回空值。 这可能令人困惑,但如果我们调用此的备用语法,则可能会变得更加明显: common_id = ANY ( SELECT common_id FROM table1 t1 ) 此条件的结果是列表中所有比较的布尔乘积。当然,单个空值会产生空结果,而整个结果也会呈现为空。 我们不能肯定地说common_id不等于这个列表中的任何内容,因为至少有一个值是NULL。 假设我们有这些数据: common -- 1 3 table1 -- NULL 1 2 LEFT JOIN / IS NULL 和 NOT EXISTS 将返回 3, NOT IN 将不返回任何东西 (因为它的值总是为FALSE或NULL)。 在MySQL中,对于非空列,LEFT JOIN / IS NULL和NOT In要比NOT EXISTS稍微高效一些(几个百分点)。如果该列是可空的,那么NOT EXISTS是最有效的(同样,不是很多)。 在Oracle中,所有三个查询都产生相同的计划( 一个ANTI JOIN)。 在SQL Server中,NOT In / NOT EXISTS更有效,因为LEFT JOIN/ IS NULL不能被其优化器优化为ANTI JOIN。 在PostgreSQL中,LEFT JOIN / IS NULL和NOT EXISTS比NOT In更有效,因为它们被优化为ANTI JOIN,而 NOT IN使用散列子计划(如果子查询太大而不能散列,甚至可以使用普通的子计划)

游客fq23g2xpzrsks 2019-12-21 14:16:22 0 浏览量 回答数 0

回答

估计是列名冲突,select后查询项都加上别名 跟列名没有关系吧 <blockquote> 01779, 00000, "cannot modify a column which maps to a non key-preserved table" // *Cause: An attempt was made to insert or update columns of a join view which //         map to a non-key-preserved table. // *Action: Modify the underlying base tables directly. 给表增加主键?改变表结构方法肯定是不对的 <pre><code>--没见过update后面跟子查询的 update test t1 from ( select id1,id2,max(v1)v1 from test2 t2 group by id1,id2 )tt where t1.id1=tt.id1 and t1.id2=tt.id2 set t1.col1=tt.v1; 随手写的,试试看 <pre><code>update test1 t1 set t1.col1=(select max(t2.v1) from test2 t2 where t1.id1=t2.id1 and t1.id2=t2.id2) where exists (select 0 from test2 t2 where t1.id1=t2.id1 and t1.id2=t2.id2);   我的test2表可能是一个比较复杂的查询语句,所以我才考虑使用update(子查询)这种方式来更新表的。你的方法对我这种情况不适用。

爱吃鱼的程序员 2020-06-07 17:48:31 0 浏览量 回答数 0

问题

技术运维问题 - MYSQL使用 -迁入RDS后为什么数据库变慢的分析

李沃晟 2019-12-01 21:43:13 986 浏览量 回答数 0

回答

好的,我编写了PHP类来扩展Zend Framework DB表,行和行集类。无论如何,我一直在开发它,因为我在PHP Tek-X上谈论了两周有关分层数据模型的内容。 我不想将我所有的代码发布到Stack Overflow,因为如果这样做,它们将隐式地获得知识共享许可。 更新:我将代码提交给Zend Framework Extras孵化器,在幻灯片共享中,我的演示文稿是带有SQL和PHP的分层数据模型。 我将用伪代码描述解决方案。我使用的是动物学分类学作为测试数据,可从ITIS.gov下载。该表是longnames: CREATE TABLE longnames ( tsn int(11) NOT NULL, completename varchar(164) NOT NULL, PRIMARY KEY (tsn), KEY tsn (tsn,completename) ) 我为分类法层次结构中的路径创建了一个封闭表: CREATE TABLE closure ( a int(11) NOT NULL DEFAULT '0', -- ancestor d int(11) NOT NULL DEFAULT '0', -- descendant l tinyint(3) unsigned NOT NULL, -- levels between a and d PRIMARY KEY (a,d), CONSTRAINT closure_ibfk_1 FOREIGN KEY (a) REFERENCES longnames (tsn), CONSTRAINT closure_ibfk_2 FOREIGN KEY (d) REFERENCES longnames (tsn) ) 给定一个节点的主键,您可以通过以下方式获取其所有后代: SELECT d.*, p.a AS _parent FROM longnames AS a JOIN closure AS c ON (c.a = a.tsn) JOIN longnames AS d ON (c.d = d.tsn) LEFT OUTER JOIN closure AS p ON (p.d = d.tsn AND p.l = 1) WHERE a.tsn = ? AND c.l <= ? ORDER BY c.l; 联接要closure AS p包括每个节点的父ID。 该查询很好地利用了索引: +----+-------------+-------+--------+---------------+---------+---------+----------+------+-----------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+---------------+---------+---------+----------+------+-----------------------------+ | 1 | SIMPLE | a | const | PRIMARY,tsn | PRIMARY | 4 | const | 1 | Using index; Using filesort | | 1 | SIMPLE | c | ref | PRIMARY,d | PRIMARY | 4 | const | 5346 | Using where | | 1 | SIMPLE | d | eq_ref | PRIMARY,tsn | PRIMARY | 4 | itis.c.d | 1 | | | 1 | SIMPLE | p | ref | d | d | 4 | itis.c.d | 3 | | +----+-------------+-------+--------+---------------+---------+---------+----------+------+-----------------------------+ 鉴于我有490,032行longnames和4,299,883行closure,它的运行时间相当不错: +--------------------+----------+ | Status | Duration | +--------------------+----------+ | starting | 0.000257 | | Opening tables | 0.000028 | | System lock | 0.000009 | | Table lock | 0.000013 | | init | 0.000048 | | optimizing | 0.000032 | | statistics | 0.000142 | | preparing | 0.000048 | | executing | 0.000008 | | Sorting result | 0.034102 | | Sending data | 0.001300 | | end | 0.000018 | | query end | 0.000005 | | freeing items | 0.012191 | | logging slow query | 0.000008 | | cleaning up | 0.000007 | +--------------------+----------+ 现在,我对上述SQL查询的结果进行后处理,根据层次结构(伪代码)将行分类为子集: while ($rowData = fetch()) { $row = new RowObject($rowData); $nodes[$row["tsn"]] = $row; if (array_key_exists($row["_parent"], $nodes)) { $nodes[$row["_parent"]]->addChildRow($row); } else { $top = $row; } } return $top; 我还为“行”和“行集”定义类。行集基本上是行的数组。行包含行数据的关联数组,还包含其子级的行集。叶节点的子行集为空。 行和行集还定义了称为的方法toArrayDeep(),这些方法以纯数组的形式递归地转储其数据内容。 然后,我可以像这样一起使用整个系统: // Get an instance of the taxonomy table data gateway $tax = new Taxonomy(); // query tree starting at Rodentia (id 180130), to a depth of 2 $tree = $tax->fetchTree(180130, 2); // dump out the array var_export($tree->toArrayDeep()); 输出如下: array ( 'tsn' => '180130', 'completename' => 'Rodentia', '_parent' => '179925', '_children' => array ( 0 => array ( 'tsn' => '584569', 'completename' => 'Hystricognatha', '_parent' => '180130', '_children' => array ( 0 => array ( 'tsn' => '552299', 'completename' => 'Hystricognathi', '_parent' => '584569', ), ), ), 1 => array ( 'tsn' => '180134', 'completename' => 'Sciuromorpha', '_parent' => '180130', '_children' => array ( 0 => array ( 'tsn' => '180210', 'completename' => 'Castoridae', '_parent' => '180134', ), 1 => array ( 'tsn' => '180135', 'completename' => 'Sciuridae', '_parent' => '180134', ), 2 => array ( 'tsn' => '180131', 'completename' => 'Aplodontiidae', '_parent' => '180134', ), ), ), 2 => array ( 'tsn' => '573166', 'completename' => 'Anomaluromorpha', '_parent' => '180130', '_children' => array ( 0 => array ( 'tsn' => '573168', 'completename' => 'Anomaluridae', '_parent' => '573166', ), 1 => array ( 'tsn' => '573169', 'completename' => 'Pedetidae', '_parent' => '573166', ), ), ), 3 => array ( 'tsn' => '180273', 'completename' => 'Myomorpha', '_parent' => '180130', '_children' => array ( 0 => array ( 'tsn' => '180399', 'completename' => 'Dipodidae', '_parent' => '180273', ), 1 => array ( 'tsn' => '180360', 'completename' => 'Muridae', '_parent' => '180273', ), 2 => array ( 'tsn' => '180231', 'completename' => 'Heteromyidae', '_parent' => '180273', ), 3 => array ( 'tsn' => '180213', 'completename' => 'Geomyidae', '_parent' => '180273', ), 4 => array ( 'tsn' => '584940', 'completename' => 'Myoxidae', '_parent' => '180273', ), ), ), 4 => array ( 'tsn' => '573167', 'completename' => 'Sciuravida', '_parent' => '180130', '_children' => array ( 0 => array ( 'tsn' => '573170', 'completename' => 'Ctenodactylidae', '_parent' => '573167', ), ), ), ), ) 关于计算深度-或实际上每个路径的长度,发表您的评论。 假设您刚刚在表中插入了一个包含实际节点的新节点(longnames在上面的示例中),则新节点的ID由LAST_INSERT_ID()MySQL 返回,否则您可以通过某种方式获取它。 INSERT INTO Closure (a, d, l) SELECT a, LAST_INSERT_ID(), l+1 FROM Closure WHERE d = 5 -- the intended parent of your new node UNION ALL SELECT LAST_INSERT_ID(), LAST_INSERT_ID(), 0;来源:stack overflow

保持可爱mmm 2020-05-17 21:46:14 0 浏览量 回答数 0

问题

MaxCompute用户指南:SQL:INSERT操作

行者武松 2019-12-01 22:02:56 1797 浏览量 回答数 0

回答

方式一:试试用max聚合: 顺序:max聚合leng-->max聚合seaout-->max聚合seain sql如下: select C.vessel_cn,C.seain,C.maxSeaout,C.maxLength,max(C.seain) as maxSeain from ( select B.vessel_cn,B.seain,B.maxLength,max(B.seaout) as maxSeaout from ( select A.vessel_cn,A.seain,A.seaout,max(A.leng) as maxLength from 你的视图 A group by A.vessel_cn,A.seain,A.seaout ) B group by B.vessel_cn,B.seain,B.maxLength ) C group by C.vessel_cn,C.maxSeaout,C.maxLength (2)方案二:根据你列出的条件用子查询过滤掉重复的记录,sql: select A.vessel_cn,A.seain,A.seaout,A.leng from 你的视图 A where not exists (select 1 from 你的视图 B where B.vessel_cn=A.vessel_cn and B.seain=A.seain and B.seaout=A.seaout and B.leng>A.leng) and not exists (select 1 from 你的视图 C where C.vessel_cn=A.vessel_cn and C.seain=A.seain and C.seaout>A.seaout and C.leng=A.leng) and not exists (select 1 from 你的视图 D where D.vessel_cn=A.vessel_cn and D.seain>A.seain and D.seaout=A.seaout and D.leng=A.leng)

长安归故里. 2020-01-07 21:23:38 0 浏览量 回答数 0

回答

我很好奇 众所周知,好奇心以杀死猫而闻名。 那么,哪一种最快的方法是给猫皮呢? 此测试的精确蒙皮环境: Debian Squeeze上的PostgreSQL 9.0,具有不错的RAM和设置。 6.000名学生,24.000个俱乐部会员资格(数据从类似的数据库复制而来,带有真实生活的数据。) 从问题中的命名模式稍微转移:“ student.id是” student.stud_id和“ club.id在club.club_id这里”。 我在该线程中以查询的作者命名,在其中有两个索引。 我运行了所有查询几次以填充缓存,然后使用EXPLAIN ANALYZE选择了5个最好的查询。 相关指标(应该是最佳的-只要我们不具备要查询哪些俱乐部的知识): ALTER TABLE student ADD CONSTRAINT student_pkey PRIMARY KEY(stud_id ); ALTER TABLE student_club ADD CONSTRAINT sc_pkey PRIMARY KEY(stud_id, club_id); ALTER TABLE club ADD CONSTRAINT club_pkey PRIMARY KEY(club_id ); CREATE INDEX sc_club_id_idx ON student_club (club_id); club_pkey这里的大多数查询都不需要。 主键在PostgreSQL中自动实现唯一索引。 最后一个索引是为了弥补PostgreSQL 上多列索引的已知缺点: 可以将多列B树索引用于涉及该索引列的任何子集的查询条件,但是当前导(最左边)列受到约束时,该索引效率最高。 结果: EXPLAIN ANALYZE的总运行时间。 1)马丁2:44.594毫秒 SELECT s.stud_id, s.name FROM student s JOIN student_club sc USING (stud_id) WHERE sc.club_id IN (30, 50) GROUP BY 1,2 HAVING COUNT() > 1; 2)Erwin 1:33.217毫秒 SELECT s.stud_id, s.name FROM student s JOIN ( SELECT stud_id FROM student_club WHERE club_id IN (30, 50) GROUP BY 1 HAVING COUNT() > 1 ) sc USING (stud_id); 3)马丁1:31.735毫秒 SELECT s.stud_id, s.name FROM student s WHERE student_id IN ( SELECT student_id FROM student_club WHERE club_id = 30 INTERSECT SELECT stud_id FROM student_club WHERE club_id = 50); 4)Derek:2.287毫秒 SELECT s.stud_id, s.name FROM student s WHERE s.stud_id IN (SELECT stud_id FROM student_club WHERE club_id = 30) AND s.stud_id IN (SELECT stud_id FROM student_club WHERE club_id = 50); 5)欧文2:2.181毫秒 SELECT s.stud_id, s.name FROM student s WHERE EXISTS (SELECT * FROM student_club WHERE stud_id = s.stud_id AND club_id = 30) AND EXISTS (SELECT * FROM student_club WHERE stud_id = s.stud_id AND club_id = 50); 6)肖恩:2.043毫秒 SELECT s.stud_id, s.name FROM student s JOIN student_club x ON s.stud_id = x.stud_id JOIN student_club y ON s.stud_id = y.stud_id WHERE x.club_id = 30 AND y.club_id = 50; 后三个的表现几乎相同。4)和5)得出相同的查询计划。 后期添加: 花式SQL,但性能跟不上。 7)超级立方体1:148.649毫秒 SELECT s.stud_id, s.name FROM student AS s WHERE NOT EXISTS ( SELECT * FROM club AS c WHERE c.club_id IN (30, 50) AND NOT EXISTS ( SELECT * FROM student_club AS sc WHERE sc.stud_id = s.stud_id AND sc.club_id = c.club_id ) ); 8)ypercube 2:147.497毫秒 SELECT s.stud_id, s.name FROM student AS s WHERE NOT EXISTS ( SELECT * FROM ( SELECT 30 AS club_id UNION ALL SELECT 50 ) AS c WHERE NOT EXISTS ( SELECT * FROM student_club AS sc WHERE sc.stud_id = s.stud_id AND sc.club_id = c.club_id ) ); 不出所料,这两个的表现几乎相同。查询计划会导致表扫描,而计划者在这里找不到使用索引的方法。 9)Wildplasser 1:49.849毫秒 WITH RECURSIVE two AS ( SELECT 1::int AS level , stud_id FROM student_club sc1 WHERE sc1.club_id = 30 UNION SELECT two.level + 1 AS level , sc2.stud_id FROM student_club sc2 JOIN two USING (stud_id) WHERE sc2.club_id = 50 AND two.level = 1 ) SELECT s.stud_id, s.student FROM student s JOIN two USING (studid) WHERE two.level > 1; 精美的SQL,CTE的性能不错。非常奇特的查询计划。 同样,有趣的是9.1如何处理这个问题。我将很快将此处使用的数据库集群升级到9.1。也许我会重新运行整个shebang ... 10)Wildplasser 2:36.986毫秒 WITH sc AS ( SELECT stud_id FROM student_club WHERE club_id IN (30,50) GROUP BY stud_id HAVING COUNT() > 1 ) SELECT s. FROM student s JOIN sc USING (stud_id); 查询2的CTE变体。出乎意料的是,它可能会导致使用完全相同的数据的查询计划略有不同。我在上找到了顺序扫描student,其中子查询变量使用了索引。 11)超级立方体3:101.482毫秒 另一个后期添加@ypercube。有多少种方法真令人惊讶。 SELECT s.stud_id, s.student FROM student s JOIN student_club sc USING (stud_id) WHERE sc.club_id = 10 -- member in 1st club ... AND NOT EXISTS ( SELECT * FROM (SELECT 14 AS club_id) AS c -- can't be excluded for missing the 2nd WHERE NOT EXISTS ( SELECT * FROM student_club AS d WHERE d.stud_id = sc.stud_id AND d.club_id = c.club_id ) ) 12)欧文3:2.377毫秒 @ypercube的11)实际上只是这个更简单的变体的令人费解的逆向方法,它也仍然缺少。执行几乎与顶级猫一样快。 SELECT s.* FROM student s JOIN student_club x USING (stud_id) WHERE sc.club_id = 10 -- member in 1st club ... AND EXISTS ( -- ... and membership in 2nd exists SELECT * FROM student_club AS y WHERE y.stud_id = s.stud_id AND y.club_id = 14 ) 13)欧文4:2.375毫秒 难以置信,但这是另一个全新的变体。我认为有超过两个成员的潜力,但它也仅以两个而跻身顶级猫之列。 SELECT s.* FROM student AS s WHERE EXISTS ( SELECT * FROM student_club AS x JOIN student_club AS y USING (stud_id) WHERE x.stud_id = s.stud_id AND x.club_id = 14 AND y.club_id = 10 )来源:stack overflow

保持可爱mmm 2020-05-08 10:56:00 0 浏览量 回答数 0

问题

如何使用 OSS 外部表同步数据

云栖大讲堂 2019-12-01 21:28:11 1508 浏览量 回答数 0

回答

您需要一张包含所有字母的表格。您可以使用UNION ALL和FROM-less 来使用临时派生表SELECT。然后,一种方法是使用相关子查询并NOT EXISTS检查不在任何电子邮件地址的第一位的字母。 SELECT l.letter FROM (SELECT 'a' letter UNION ALL SELECT 'b' letter ... SELECT 'y' letter UNION ALL SELECT 'z' letter) l WHERE NOT EXISTS (SELECT * FROM customers c WHERE left(lower(emailaddress), 1) = l.letter);

祖安文状元 2020-01-05 14:34:11 0 浏览量 回答数 0

问题

MaxCompute最佳实践:修改不兼容SQL实战

行者武松 2019-12-01 22:09:22 4078 浏览量 回答数 0

问题

Java-SDK之如何实现管理Bucket?

青衫无名 2019-12-01 21:39:33 1239 浏览量 回答数 0

问题

EXISTS与IN的子查询-MySQL?mysql

保持可爱mmm 2020-05-17 12:09:15 0 浏览量 回答数 1

回答

1 and or 使用 >db.col.find({$or:[{key1: value1}, {key2:value2}]}) 12 where使用,和sql一样 查询已经有回款,但是没有完成回款的订单 >order >db.info.find({'$where': "this.price > this.received_money",status:2}).count() 123 条件操作符号 (>) 大于 - $gt(<) 小于 - $lt(>=) 大于等于 - $gte(<= ) 小于等于 - $ltedb.col.find({likes : {$lt : 150}}) 4 数组嵌套查询 rosterdb.domain_set.find({}) { "_id" : ObjectId("55cdb554b9518f0121a9870f"), "did" : NumberLong(75707), "hide_account" : 0, "pds" : { "details" : [ { "key" : "姓名", "type" : 0, "check" : 1 }, { "key" : "性别", "type" : 0, "check" : 1 }, { "key" : "联系方式", "type" : 0, "check" : 1 }, { "key" : "部门", "type" : 0, "check" : 1 }, { "key" : "职位", "type" : 0, "check" : 1 }, { "key" : "工号", "type" : 0 }, { "key" : "邮箱", "type" : 0 }, { "key" : "地址", "type" : 0 }, { "key" : "生日", "type" : 1 }, { "key" : "籍贯", "type" : 1 }, { "key" : "民族", "type" : 1 }, { "key" : "身份证号", "type" : 1, "check" : 1 }, { "key" : "婚姻状况", "type" : 1 }, { "key" : "子女", "type" : 1, "check" : 1 }, { "key" : "家庭住址", "type" : 1 }, { "key" : "紧急联系人", "type" : 1 }, { "key" : "紧急联系电话", "type" : 1 }, { "key" : "毕业日期", "type" : 1 }, { "key" : "入职日期", "type" : 1, "check" : 1 }, { "key" : "111", "type" : 3, "show_name" : "111", "check" : 1 }, { "key" : "222", "type" : 3, "show_name" : "222" }, { "key" : "333", "type" : 3, "show_name" : "333", "check" : 1 } ], "key_alloc" : 100 }, "udversion" : 50 } { "_id" : ObjectId("55d693c2b9518f0121ada57f"), "did" : NumberLong(11111), "hide_account" : 0, "udversion" : 1 } db.domain_set.find({"pds.details":{"$elemMatch":{"show_name" : "1111"}}}) db.test.find({"pds.details.19.key":"1111"}) 5 只显示某几个字段 查询did=10000的公司下面的订单,只显示price和order_id字段 order db.info.find({did:10000},{price:1,order_id:1}) 6 分页查询–limit和skip 查询did=10000的已经确认的订单,按照order_id(最新创建时间排序) order 显示前15个,第一页 db.info.find({did:10000,status:2},{order_id:1,price:1}).sort({order_id:-1}).limit(15) 加载16到30页,第二页 db.info.find({did:10000,status:2},{order_id:1,price:1}).sort({order_id:-1}).limit(15).skip(15) 7 aggregate使用,相当于shell里面的”|” 上面的几乎全部可以用aggregate进行查询 与sql对应关系 sql mongodb WHERE $match //match里面可以用and,or,以及逻辑判断,但是好像不能用whereGROUP BY $groupHAVING $matchSELECT $projectORDER BY $sortLIMIT $limitSUM() $sumCOUNT() $sum 特殊:暂时还没有用到$unwind 将数组元素拆分为独立字段$goNear 会返回一些坐标值,这些值以按照距离指定点距离由近到远进行排序 数字运算符$multiply 乘$add 加$subtract 减$mod 取模$divide 除 order项目中使用:1 统计某一段时间的订单总额和订单数量:db.info.aggregate([ { $match:{ did:10000, status:2, ordered_time:{$gt:1488297600000,$lt:1490976000000} } }, { $group: { _id: null, total: { $sum: "$price" }, order_num:{$sum:1} } } ])2 按照未回款的金额大小排序,同时显示订单金额,未回款金额db.info.aggregate([ { $match:{ did:10000, status:2, ordered_time:{$gt:1488297600000,$lt:1490976000000} } }, { $project:{ price:1, did:1, order_id:1, notpay:{$subtract:["$price","$received_money"]} } }, { $sort:{ notpay:-1 } } ]) 8 其他实例: 2 统计已经完成回款的订单 db.info.find({ $or:[{'$where': "this.price <= this.received_money"},{price:0}], did:10000, status:2, ordered_time:{$gt:1488297600000,$lt:1490976000000} }, {price:1}).sort({price:-1}) 3 查询所有未完成回款的订单1 db.info.find({ $or:[{'$where': "this.price > this.received_money"},{received_money:{$exists:false}}], did:10000, status:2, ordered_time:{$gt:1488297600000,$lt:1490976000000} }, {price:1}).sort({price:-1})

小六码奴 2019-12-02 02:02:28 0 浏览量 回答数 0

回答

详细解答可以参考官方帮助文档 云数据库 Redis 版兼容 Redis 3.0 版本,支持 Redis 3.0 的 Geo 命令。目前还有小部分暂未开放的命令和受限制的命令。 支持的命令操作 Keys(键) String(字符串) Hash(哈希表) List(列表) Set(集合) SortedSet(有序集合) DEL APPEND HDEL BLPOP SADD ZADD DUMP BITCOUNT HEXISTS BRPOP SCARD ZCARD EXISTS BITOP HGET BRPOPLPUSH SDIFF ZCOUNT EXPIRE BITPOS HGETALL LINDEX SDIFFSTORE ZINCRBY EXPIREAT DECR HINCRBY LINSERT SINTER ZRANGE MOVE DECRBY HINCRBYFLOAT LLEN SINTERSTORE ZRANGEBYSCORE PERSIST GET HKEYS LPOP SISMEMBER ZRANK PEXPIRE GETBIT HLEN LPUSH SMEMBERS ZREM PEXPTREAT GETRANGE HMGET LPUSHX SMOVE ZREMRANGEBYRANK PTTL GETSET HMSET LRANGE SPOP ZREMRANGEBYSCORE RANDOMKEY INCR HSET LREM SRANDMEMBER ZREVRANGE RENAME INCRBY HSETNX LSET SREM ZREVRANGEBYSCORE RENAMENX INCRBYFLOAT HVALS LTRIM SUNION ZREVRANK RESTORE MGET HSCAN RPOP SUNIONSTORE ZSCORE SORT MSET RPOPLPUSH SSCAN ZUNIONSTORE TTL MSETNX RPUSH ZINTERSTORE TYPE PSETEX RPUSHX ZSCAN SCAN SET ZRANGEBYLEX OBJECT SETBIT ZLEXCOUNT SETEX ZREMRANGEBYLEX SETNX SETRANGE STRLEN 以及 HyperLogLog Pub/Sub(发布/订阅) Transaction(事务) Connection(连接) Server(服务器) Scripting(脚本) Geo(地理位置) PFADD PSUBSCRIBE DISCARD AUTH FLUSHALL EVAL GEOADD PFCOUNT PUBLISH EXEC ECHO FLUSHDB EVALSHA GEOHASH PFMERGE PUBSUB MULTI PING DBSIZE SCRIPT EXISTS GEOPOS PUNSUBSCRIBE UNWATCH QUIT TIME SCRIPT FLUSH GEODIST SUBSCRIBE WATCH SELECT INFO SCRIPT KILL GEORADIUS UNSUBSCRIBE KEYS SCRIPT LOAD GEORADIUSBYMEMBER CLIENT KILL CLIENT LIST CLIENT GETNAME CLIENT SETNAME CONFIG GET MONITOR SLOWLOG 说明 集群实例下,client list 命令列出所有连接到该 proxy 的 user connection。其中,id、age、idle、addr、fd、name、db、multi、omem、cmd 字段和redis内核表达的意思一样。sub、psub 在 proxy 层没有区分,要么都为1,要么都为0。qbuf、qbuf-free、obl、oll 字段目前没有意义。 集群实例下,client kill 命令目前支持两种形式:client kill ip:port和client kill addr ip:port。 暂未开放的命令 Keys(键) Server(服务器) MIGRATE BGREWRITEAOF BGSAVE CONFIG REWRITE CONFIG SET CONFIG RESETSTAT COMMAND COMMAND COUNT COMMAND GETKEYS COMMAND INFO DEBUG OBJECT DEBUG SEGFAULT LASTSAVE ROLE SAVE SHUTDOWN SLAVEOF SYNC 集群实例受限制的命令 Keys Strings Lists HyperLogLog Transaction Scripting RENAME MSETNX RPOPLPUSH PFMERGE DISCARD EVAL RENAMENX BRPOP PFCOUNT EXEC EVALSHA SORT BLPOP MULTI SCRIPT EXISTS BRPOPLPUSH UNWATCH SCRIPT FLUSH WATCH SCRIPT KILL SCRIPT LOAD 说明 集群实例受限命令只支持所操作 key 均分布在单个 hash slot 中的场景,没有实现多个 hash slot 数据的合并功能,因此需要用 hash tag 的方式确保要操作的 key 均分布在一个 hash slot 中。 比如有 key1,aakey,abkey3,那么我们在存储的时候需要用 {key}1,aa{key},ab{key}3 的方式存储,这样调用受限命令时才能生效。具体关于 hash tag 的用法请参见 Redis 官方文档:http://redis.io/topics/cluster-spec。 事务之前没有使用 watch 命令且事务中都是单 key 的命令场景,不再要求所有 key 必须在同一个 slot 中,使用方式和直连 redis 完全一致。其他场景要求事务中所有命令的所有 key 必须在同一个 slot 中。 多 key 命令包括:DEL、SORT、MGET、MSET、BITOP、EXISTS、MSETNX、RENAME、 RENAMENX、BLPOP、BRPOP、RPOPLPUSH、BRPOPLPUSH、SMOVE、SUNION、SINTER、SDIFF、SUNIONSTORE、SINTERSTORE、SDIFFSTORE、ZUNIONSTORE、ZINTERSTORE、 PFMERGE、PFCOUNT。 不允许在事务中使用的命令包括:WATCH、UNWATCH、RANDOMKEY、KEYS、SUBSCRIBE、 UNSUBSCRIBE、PSUBSCRIBE、PUNSUBSCRIBE、PUBLISH、PUBSUB、SCRIPT、EVAL、 EVALSHA、SCAN、ISCAN、DBSIZE、ADMINAUTH、AUTH、PING、ECHO、FLUSHDB、 FLUSHALL、MONITOR、IMONITOR、RIMONITOR、INFO、IINFO、RIINFO、CONFIG、 SLOWLOG、TIME、CLIENT。 Lua使用限制 Lua 脚本放开限制,标准版-双节点、标准版-单节点支持用户直接调用。 集群版本条件性支持: 所有key都应该由 KEYS 数组来传递,redis.call/pcall 中调用的redis命令,key的位置必须是KEYS array(不能使用Lua变量替换KEYS),否则直接返回错误信息,"-ERR bad lua script for redis cluster, all the keys that the script uses should be passed using the KEYS array\r\n"。 所有key必须在1个slot上,否则返回错误信息,"-ERR eval/evalsha command keys must be in same slot\r\n"。 调用必须要带有key,否则直接返回错误信息, "-ERR for redis cluster, eval/evalsha number of keys can't be negative or zero\r\n"。 自研的集群实例命令 info key 命令:查询 key 所属的 slot 和 db。Redis 原生的 info 命令中最多可以带一个可选的 section (info [section])。目前云数据库 Redis 版的集群实例,部分命令限制所有 key 必须在同一个 slot 中,info key 命令方便用户查询某些 key 是否在同一个 slot 或 db 节点中。用法如下: 127.0.0.1:6379> info key test_key slot:15118 node_index:0 注意 线上旧版本可能出现 info key 显示出来的 node index 和实例拓扑图的 node index 不一致,最新版本已经修复。 info key 显示的 node 是指集群规格下后端的物理节点,和 select 命令中的 db 不是同一个概念。 iinfo 命令:用法类似于 info,用于在指定的 Redis 节点上执行 info 命令。用法如下: iinfo db_idx [section] 其中,db_idx 的范围是[0, nodecount],nodecount 可以通过 info 命令获取,section 为 info 官方一致的值。要了解某个 Redis 节点的 info 可以使用 iinfo 命令或者从控制台上查看实例拓扑图,详情请参见 如何查看 Redis 集群子实例内存。 riinfo 命令:和 iinfo 命令类似,但只能在读写分离的模式下使用。用法中增加了一个 readonly slave 的 idx,用于指定在第几个 readonly slave 上执行 info 命令。在读写分离集群中可以用来在指定 readonly slave 上执行 info 命令。如果在非读写分离集群中使用,会返回错误。用法如下: riinfo db_idx ro_slave_idx [section] iscan 命令:在集群模式下可以在指定的 db 节点上执行 scan 命令。在 scan 命令的基础上扩展了一个参数用于指定 db_idx, db_idx 的范围是[0, nodecount],nodecount 可以通过 info 命令获取或者从控制台上查看实例拓扑图。用法如下: iscan db_idx cursor [MATCH pattern] [COUNT count] imonitor 命令:和 iinfo, iscan 类似,在 monitor 的基础上新增一个参数指定 monitor 执行的 db_idx,db_idx 的范围是[0, nodecount), nodecount 可以通过 info 命令获取或者从控制台上查看实例拓扑图。用法如下: imonitor db_idx rimonitor 命令:和 riinfo 类似,用于读写分离场景下,在指定的 shard 里的指定只读从库上执行 monitor 命令。用法如下: rimonitor db_idx ro_slave_idx 说明 关于 Redis 命令的详细信息,请参见 官方文档。 云数据库 Redis 版集群实例最新的命令支持详情,请参见 云栖社区说明。

2019-12-01 23:09:35 0 浏览量 回答数 0

回答

权限验证错误 HTTPStatus ErrorCode ErrorMsg 描述 重试 403 OTSAuthFailed The AccessKeyID does not exist. AccessKeyID 不存在。 否 403 OTSAuthFailed The AccessKeyID is disabled. AccessKeyID 被禁用。 否 403 OTSAuthFailed The user does not exist. 该用户不存在。 否 403 OTSAuthFailed The instance is not found. 该实例不存在。 否 403 OTSAuthFailed The user has no privilege to access the instance. 没有访问该实例的权限。 否 403 OTSAuthFailed The instance is not running. 该实例的状态不是运行中(Running)。 否 403 OTSAuthFailed Signature mismatch. 签名不匹配。 否 403 OTSAuthFailed Mismatch between system time and x-ots-date: {Date}. 服务器时间与请求 header 中 x-ots-date 的时间相差超过一定范围。 否 HTTP 消息错误 HTTPStatus ErrorCode ErrorMsg 描述 重试 413 OTSRequestBodyTooLarge The size of POST data is too large 用户 POST 请求发送的数据过大。 否 408 OTSRequestTimeout Request timeout. 客户端完成请求的时间过长。 否 405 OTSMethodNotAllowed OTSMethodNotAllowedOnly POST method for requests is supported. 仅支持 POST 方式的请求。 否 403 OTSAuthFailed Mismatch between MD5 value of request body and x-ots-contentmd5 in header. 根据请求 Body 数据计算的 MD5 与请求 header 中包含的 x-ots-contentmd5 值不同。 否 400 OTSParameterInvalid Missing header: {HeaderName}. 请求中缺少必要的 header。 否 400 OTSParameterInvalid Invalid date format: {Date}. 时间格式不合法。 否 400 OTSParameterInvalid Unsupported operation: {Operation}. 请求的 URL 中的操作名不合法。 否 400 OTSParameterInvalid Can not reserve read capacity unit on capacity. 容量型实例下的表不支持设置留读/写吞吐量。 否 400 OTSForbiddenUpdateCapacityUnit Your instance is forbidden to update capacity unit. 容量型实例下的表不支持调整留读/写吞吐量。 否 API错误 HTTPStatus ErrorCode ErrorMsg 描述 重试 500 OTSInternalServerError Internal server error. 内部错误。如果出现该错误,请提交工单。 是 403 OTSQuotaExhausted Too frequent table operations. 执行表相关的操作过于频繁。 是 403 OTSQuotaExhausted Number of tables exceeded the quota. 表的数量超过定额。 否 400 OTSParameterInvalid Invalid instance name: {InstanceName}. 实例名称不合法。 否 400 OTSParameterInvalid Invalid table name: {TableName}. 表名不合法。 否 400 OTSParameterInvalid Invalid column name: {ColumnName}. 列名名称不合法。 否 400 OTSParameterInvalid {ColumnType} is an invalid type for the primary key. 主键列类型不合法。 否 400 OTSParameterInvalid {ColumnType} is an invalid type for the attribute column. 属性列类型不合法。 否 400 OTSParameterInvalid The number of primary key columns must be in range: [1, {Limit}]. 主键列的列数不能为 0,不能超出限制。 否 400 OTSParameterInvalid Value of column {ColumnName} must be UTF8 encoding. 此列列值必须为 UTF8 编码。 否 400 OTSParameterInvalid The length of attribute column: {ColumnName} exceeded the MaxLength:{MaxSize} with Current Length:{CellSize}. 属性列名长度超出命名最大长度限制。 否 400 OTSParameterInvalid No row specified in the request of BatchGetRow. BatchGetRow 请求中未指定任何行。 否 400 OTSParameterInvalid Duplicated table name: {TableName}. 在 BatchGetRow 或 BatchWriteRow 操作中包含同名的表。 否 400 OTSParameterInvalid Duplicated primary key name: '{PKName}'. 主键重复。 否 400 OTSParameterInvalid The limit must be greater than 0. limit 参数必须大于 0。 否 400 OTSParameterInvalid Duplicated attribute column name with primary key column: {ColumnName}. 对某行进行操作时,包含与主键列同名的属性列。 否 400 OTSParameterInvalid Rows count exceeds the upper limit:{limit}. 这次写入的行总数超过了最大限制:limit。 否 400 OTSParameterInvalid No version condition is specified while querying row. 查询的时候没有指定版本数。 否 400 OTSParameterInvalid No row is specified in BatchWriteRow BatchWriteRow 操作中没有行数据,目前 BatchWriteRow 必须至少包含一行。 否 400 OTSParameterInvalid No operation is specified for table:{TableName} BatchWriteRow 操作中对于表 TableName 没有包含任何操作。 否 400 OTSParameterInvalid The type of row in batch write operation is invalid BatchWriteRow 操作中的行类型不合法。 否 400 OTSParameterInvalid The modify type is invalid BatchWriteRow 操作中的类型不对,目前仅支持 PUT、UPDATE 和 DELETE。 否 400 OTSParameterInvalid The total data size of BatchWriteRow request exceeds the limit, limit size: {LimitSize}, data size:{UserSize} 一次 BatchWriteRow 操作中的总大小超过了限制。 否 400 OTSParameterInvalid Time-to-live is missing while creating table 创建表的时候没有指定 TTL 值。 否 400 OTSParameterInvalid MaxVersions is missing while creating table 创建表的时候没有指定最大版本数。 否 400 OTSParameterInvalid Start and end time must be given at the same time GetRange 操作中需要同时指定 StartTime 和 EndTime。 否 400 OTSParameterInvalid Invalid column type, only STRING,INTEGER,BINARY is allowed. 列类型错误,目前主键列仅支持 STRING、INTEGER 和 BINARY。 否 400 OTSParameterInvalid Invalid column type: {ColumnType} 列类型不合法。 否 400 OTSParameterInvalid Invalid return type: {ReturnType} 返回类型不合法。 否 400 OTSParameterInvalid Invalid condition:{Condition} 指定的条件不合法。 否 400 OTSParameterInvalid The value of read capacity unit can not be less than {Limit} 读 CU 值不能小于 Limit。 否 400 OTSParameterInvalid The value of write capacity unit can not be less then {Limit} 写 CU 值不能小于 Limit。 否 400 OTSParameterInvalid first primary key can’t be AUTO_INCREMENT 第一个主键不能设置为自增列。 否 400 OTSParameterInvalid AUTO_INCREMENT primary key must be integer 只有整数列可以被设置为自增列。 否 400 OTSParameterInvalid AUTO_INCREMENT primary key count must <= 1 最多只能设置一个自增列。 否 400 OTSParameterInvalid Column value cannot be given when type is DELETE_ONE_VERSION,DELETE_ALL_VERSION 当使用了 DELETE_ONE_VERSION 或 DELETE_ALL_VERSION 等删除操作时,不能设置属性值。 否 400 OTSParameterInvalid Timestamp must be given when type is DELETE_ONE_VERSION 当删除一个版本时必须设置版本号。 否 400 OTSParameterInvalid Timestamp cannot be given when type is DELETE_ALL_VERSION 当删除所有版本时不能设置版本号。 否 400 OTSParameterInvalid No name is given for attribute column 属性列缺少名字。 否 400 OTSParameterInvalid No value is given for column name 属性列缺少值。 否 400 OTSParameterInvalid OpType cannot be given for column name:{ColumnName} in PutRow PutRow 时不能指定操作类型,只有 UpdateRow 才需要指定操作类型。 否 400 OTSParameterInvalid Attribute column is missing 缺少属性列。 否 400 OTSParameterInvalid The number of attribute columns exceeds the limit, limit count:{Limit} , column count: {Count} 列的个数超过了 Limit 限制。 否 400 OTSParameterInvalid The length of primary key column: {ColumnName} exceeds the MaxLength: {Limit} with CurrentLength: {Current} 主键的长度超过了限制。 否 400 OTSParameterInvalid No name is given for primary key 主键列中没有设置名字。 否 400 OTSParameterInvalid No value is given for primary key name:{PkName} 主键列没有设置值。 否 400 OTSParameterInvalid OpType cannot be given for primary key name :{PkName} 主键中不能指定操作类型。 否 400 OTSParameterInvalid Timestamp cannot be given for primary key name:{PkName} 主键中不能指定时间戳。 否 400 OTSParameterInvalid Duplicated primary key name: {PkName} 主键重复。 否 400 OTSParameterInvalid Attribute column cannot be given while reading data 读取数据的时候不需要指定列值。 否 400 OTSParameterInvalid Delete marker cannot be given 非 Delete 时都不能指定 DeleteMarker。 否 400 OTSParameterInvalid The number of columns from the request exceeds the limit, limit count: {Limit} , column count:{current} 请求的列的个数超过限制。 否 400 OTSParameterInvalid Timestamp must be in range [0, INT64_MAX/1000) 时间戳必须大于等于 0,小于 INT64_MAX/1000。 否 400 OTSParameterInvalid TimeToLive cannot be 0 or less than -1 TTL 不能设置为 0 或者小于 -1 的值,但可以设置为 -1。 否 400 OTSParameterInvalid The maximum versions cannot be less than or equal to 0 最大版本数不能小于等于 0。 否 400 OTSParameterInvalid Specific timestamp cannot be less than 0 指定的时间戳不能小于 0。 否 400 OTSParameterInvalid The maximum deviation must be in range [0, INT64_MAX/1000000] 最大版本偏差的值必须位于整个范围内。 否 400 OTSParameterInvalid Deserialize filter failed 反序列化 filter 失败,原因是 SDK 组装的 filter 格式不对。 否 400 OTSParameterInvalid Offset in ColumnPaginationFilter must be greater than or equal to 0 ColumnPaginationFilter 过滤器的 offset 必须大于等于 0。 否 400 OTSParameterInvalid Limit in ColumnPaginationFilter must be greater than 0 ColumnPaginationFilter 过滤器的 Limit 必须大于等于 0。 否 400 OTSParameterInvalid Deserialize relation filter failed 反序列化单列过滤器失败,原因可能是 SDK 中组装的 filter 格式不对。 否 400 OTSParameterInvalid Deserialize composite filter failed 反序列化组合过滤器失败,原因可能是 SDK 中组装的 filter 格式不对。 否 400 OTSParameterInvalid Deserialize column pagination filter failed. 反序列化宽行过滤器失败,原因可能是 SDK 中组装的 filter 格式不对。 否 400 OTSParameterInvalid The count of filter exceeds the max:{Limit} 过滤器的个数超过了限制。 否 400 OTSParameterInvalid Specific tiemstamp and max versions cannot be given at the same time 单个时间戳和最大版本数不能同时存在,只能存在一个。 否 400 OTSParameterInvalid Specific tiemstamp and time range cannot be given at the same time 单个时间戳和时间戳范围不能同时存在,只能存在一个。 否 400 OTSParameterInvalid Specific tiemstamp, time range and max versions cannot be given at the same time 单个时间戳、时间戳范围和最大版本数不能同时存在,只能存在一个。 否 400 OTSParameterInvalid Duplicated attribute column name with primary key column:{PkName} 属性列重复。 否 400 OTSParameterInvalid The total data size of PutRow request exceeds the limit, limit size: {Limit} , data size: {Current} PutRow 操作的数据大小超过限制。 否 400 OTSParameterInvalid The total data size of UpdateRow request exceeds the limit, limit size: {Limit} , data size: {Current} UpdateRow 操作的数据大小超过限制。 否 400 OTSParameterInvalid No parameter is specified in table options TableOption 中没有指定任何参数。 否 400 OTSParameterInvalid Input encoded PK broken, invalidate cell key type:xx 编码的 PlainBuffer 不合法,cell 类型错误。 否 400 OTSParameterInvalid Input encoded PK broken, length is shorter than expect 编码的 PlainBuffer 不合法,长度和预期不一致。 否 400 OTSParameterInvalid PKAutoIncr can’t be used for read operations 读操作时不能指定自增属性。 否 400 OTSParameterInvalid Begin key must less than end key in FORWARD 前向查询中,开始键必须小于结束键。 否 400 OTSParameterInvalid Begin key must more than end key in BACKWARD 反向查询中,开始键必须大于结束键。 否 400 OTSParameterInvalid Repeated rows do not support row exist expectation check in BatchModify BatchWriteRow 中重复的行操作不支持行存在条件检查。 否 400 OTSParameterInvalid Repeated rows do not support row condition check in BatchModify BatchWriteRow 操作中不允许重复行存在条件更新。 否 400 OTSParameterInvalid PK column size not the same for all rows in table: {TableName} 不同行中的主键的个数不一致。 否 400 OTSParameterInvalid Duplicate rows detected in MultiPut 存在重复行。 否 400 OTSParameterInvalid Duplicate rows detected in MultiGet 存在重复行。 否 400 OTSParameterInvalid Column does not exist:{ColumnName} 列不存在。 否 400 OTSParameterInvalid Invalid max scan size: {Limit} 范围查询的 limit 超过限制。 否 400 OTSParameterInvalid data format is invalid PlainBuffer 编码的行数据不合法。 否 400 OTSParameterInvalid double can not be used as primary key 主键中不能使用 double。 否 400 OTSParameterInvalid data format is invalid, unknown variant type occured PlainBuffer 编码的行数据不合法,出现了非法的值类型。 否 400 OTSParameterInvalid Parse PBMessage from RawString failed 反序列化 protobuf 失败,可能是 SDK 序列化代码错误。 否 400 OTSParameterInvalid Cell data broken, mismatch header, actual: {Header} , expect: {Header} PlainBuffer 编码的行数据不合法,预期的 Header 不一致。 否 400 OTSParameterInvalid Cell data broken, PK value cannot be NULL, name: {PkName} PlainBuffer 编码的行数据不合法,PkName 对应的主键的值为空。 否 400 OTSParameterInvalid Cell data broken, PK is empty PlainBuffer 编码的行数据不合法,缺少主键。 否 400 OTSParameterInvalid Cell data broken, no PK follow PKTag PlainBuffer 编码的行数据不合法,主键标志后面没有按预期出现主键内容。 否 400 OTSParameterInvalid Cell data broken, attr has no name PlainBuffer 编码的行数据不合法,属性列缺少名字。 否 400 OTSParameterInvalid Cell data broken, attr has no value, name:{Name} PlainBuffer 编码的行数据不合法,属性列缺少值。 否 400 OTSParameterInvalid Cell data broken, no Cells follow CellTag PlainBuffer 编码的行数据不合法,Cell 标志后没有按预期出现 Cell 内容。 否 400 OTSParameterInvalid Cell data broken, no valid element in Cell, name: {Name} PlainBuffer 编码的行数据不合法,Cell 格式混乱。 否 400 OTSParameterInvalid Cell data broken, cell is not end with checksum[{0x0A}]”] tag. PlainBuffer 编码的行数据不合法,Cell 编码结束时没有按照预期出现 CheckSumFlag。 否 400 OTSParameterInvalid Cell data broken, row is not end with checksum tag PlainBuffer 编码的行数据不合法,行数据编码结束时没按照预期出现 CheckSumTag。 否 400 OTSParameterInvalid Cell data broken, mismatch tag, actual tag({TAG}), expect({TAG}) PlainBuffer 编码的行数据不合法,预期的 Tag 没有出现。 否 400 OTSParameterInvalid Cell data broken, wrong string format, size: {Size} PlainBuffer 编码的行数据不合法,字符串编码格式错误。 否 400 OTSParameterInvalid Invalid Capacity Unit for UpdateTable: Either read({CU}) or write({CU}) should be non-negative 读写 CU 都应该大于等于 0。 否 400 OTSParameterInvalid Auto increment pk must be integer, name: {PkName} 自增列的类型必须是整数。 否 400 OTSParameterInvalid Cannot deserialize the request data 无法反序列化请求中的数据,原因可能是空值或格式不合法。 否 400 OTSParameterInvalid Invalid row: missing checksum PlainBuffer 编码的行数据不合法,缺少行的 checksum 值。 否 400 OTSParameterInvalid Invalid Column({ColumnName}): missing checksum. PlainBuffer 编码的列数据不合法,缺少 Cell 的 checksum 值。 否 400 OTSParameterInvalid Cell data broken, checksum is mismatch, {UserChecksum} :{SeviceChecksum} : PlainBuffer 编码的行数据不合法,用户的 UserChecksum 和服务器计算的 SeviceChecksum 不一致。 否 400 OTSParameterInvalid Cell data broken, has more data in cell, but they can’t be parsed PlainBuffer 编码的列数据不合法,存在非预期的过多数据存在。 否 400 OTSParameterInvalid NaN can’t be set to double value Double 类型不能设置为 NaN 值。 否 400 OTSParameterInvalid Infinity can’t be set to double value Double 类型不能设置为 Infinity 值。 否 400 OTSParameterInvalid Invalid max versions: {Version} . Reason: Max versions must be positive 最大版本数不合法,应该大于 0 或者等于 -1。 否 400 OTSParameterInvalid invalid range, the begin’s type is different from the end’s,{BeginType}:{EndType} 范围查询中的起始键类型和结束键类型不一致。 否 400 OTSParameterInvalid Invalid offset of Filter: {Filter} . Reason: Offset must be nonnegative. 过滤器中的 offset 必须大于等于 0。 否 400 OTSParameterInvalid Invalid Capacity Unit:{CU} . Capacity Unit must be nonnegative. CU 值必须大于等于 0。 否 400 OTSParameterInvalid Unknown or unsupported CellType in primary key: {PkName} 主键的 Cell 类型无法识别。 否 400 OTSParameterInvalid Invalid boolean real value, value length: {Length} PlainBuffer 编码的列数据不合法,Bool 类型的值长度不合法。 否 400 OTSParameterInvalid invalid name of column: empty name 属性列的名字不能为空。 否 400 OTSParameterInvalid Invalid ModifyType:{ModifyType} 更新类型不合法。 否 400 OTSParameterInvalid Invalid relation operator: {Operation} 关系运算符不合法。 否 400 OTSParameterInvalid Invalid type of filter: {Type} 过滤器的类型不合法。 否 400 OTSParameterInvalid Invalid NOT operator: the number of sub-filters must be 1 NOT 运算符只允许有一个子过滤器。 否 400 OTSParameterInvalid Invalid AND/OR operator: the number of sub-filters must be 2 AND 和 OR 运算符都只需要有两个子过滤器。 否 400 OTSParameterInvalid Invalid type of sub-filter: {Filter} 子过滤器的类型不合法。 否 400 OTSParameterInvalid {Count} pk auto increment exist in row 多个 PK 自增列存在。 否 400 OTSParameterInvalid Invalid action: {Action} 非法的操作类型。 否 400 OTSParameterInvalid Invalid row-existence expectation: {Expectation} 指定的行存在性值不合法。 否 400 OTSParameterInvalid Invalid row to delete which with pk auto increment 删除时不能设置自增列属性。 否 400 OTSParameterInvalid Invalid expect:{RowExpect} when modify row with pk auto increment 使用主键列自增时,指定的行存在性值不合法。 否 400 OTSParameterInvalid Can’t set condition when modify row with pk auto increment 使用主键列自增时,不能设置 ConditionUpdate。 否 400 OTSParameterInvalid Invalid expect: {RowExpect} when modify a specific row for table with pk auto increment 修改主键列自增表的特定一行时,指定的行存在性条件不合法。 否 400 OTSParameterInvalid Invalid cell: {Cell} . missing timestamp 缺少时间戳。 否 400 OTSParameterInvalid Invalid cell timestamp: {Timestamp} . Expect: [0, Version::kMax.mVersion / kUsecPerMsec] 指定的时间戳不合法。 否 400 OTSParameterInvalid Invalid timestamp for cell: {Timestamp} . timestamp is inapplicable to DELETE_ALL_VERSION 当使用 DELETE_ALL_VERSION 删除所有版本时不能指定版本。 否 400 OTSParameterInvalid Invalid op type of cell: {OpType} 非法的操作类型。 否 400 OTSParameterInvalid Invalid cell: {Cell}. Reason: missing value Cell 非法,缺少值。 否 400 OTSParameterInvalid Invalid request of delete row: missing RowDeleteMarker in request 删除请求中没有包含 RowDeleteMarker。 否 400 OTSParameterInvalid Invalid request of put/update row: unexpected RowDeleteMarker in request. PutRow 和 UpdateRow 不能包含 RowDeleteMarker。 否 400 OTSParameterInvalid Invalid update row request: missing cells in request UpdateRow 中缺少属性列值。 否 400 OTSParameterInvalid Invalid delete row request: unexpected cells in request DeleteRow 中不应该出现属性列的值。 否 400 OTSParameterInvalid Invalid request of put row: find cells without values PutRow 中属性列缺少值。 否 400 OTSParameterInvalid Can not reserve read capacity unit on hybrid storage cluster: {TableName} 混合存储类型实例不能设置预留读 CU。 否 400 OTSParameterInvalid Can not reserve write capacity unit on hybrid storage cluster: {TableName} 混合存储类型实例不能设置预留写 CU。 否 400 OTSParameterInvalid First primary key can’t be auto increment, table: {TableName} 第一个主键不能设置为自增列。 否 400 OTSParameterInvalid the count of auto-incremental primary keys can not be more than 1 自增列的个数不能超过 1。 否 表格存储相关异常 HTTPStatus ErrorCode ErrorMsg 描述 重试 503 OTSServerBusy Server is busy. TableStore 内部服务器繁忙,稍后重试即可成功。 是 503 OTSPartitionUnavailable The partition is not available. 一般是分区加载中,稍后重试即可成功。 是 503 OTSTimeout Operation timeout. 在 TableStore 内部操作超时。 是 503 OTSServerUnavailable Server is not available. 在 TableStore 内部有服务器不可访问。 是 409 OTSRowOperationConflict Data is being modified by the other request. 多个并发的请求写同一行数据,导致冲突。 是 409 OTSObjectAlreadyExist Requested table already exists. 请求创建的表已经存在。 否 404 OTSObjectNotExist Requested table does not exist. 请求的表不存在。 否 404 OTSTableNotReady The table is not ready. 表新创建后还在做初始化,稍等几秒钟即可使用。 是 403 OTSTooFrequentReserved ThroughputAdjustment Capacity unit adjustment is too frequent. 读写能力调整过于频繁。 是 403 OTSCapacityUnitExhausted Capacity unit is not enough. 该数据分区读写服务能力耗尽。 否 403 OTSConditionCheckFail Condition check failed. 预查条件检查失败。 否 400 OTSOutOfRowSizeLimit The total data size of columns in one row exceeded the limit. 该行所有列数据大小总和超出限制。 否 400 OTSOutOfColumnCountLimit The number of columns in one row exceeded the limit. 该行总列数超出限制。 否 400 OTSInvalidPK Primary key schema mismatch. 主键不匹配。 否

保持可爱mmm 2020-03-29 15:33:10 0 浏览量 回答数 0

回答

Android平台进行数据存储的五大方式,分别如下: 1 使用SharedPreferences存储数据 2 文件存储数据 3 SQLite数据库存储数据 4 使用ContentProvider存储数据 5 网络存储数据 下面详细讲解这五种方式的特点 第一种: 使用SharedPreferences存储数据 适用范围:保存少量的数据,且这些数据的格式非常简单:字符串型、基本类型的值。比如应用程序的各种配置信息(如是否打开音效、是否使用震动效果、小游戏的玩家积分等),解锁口 令密码等 核心原理:保存基于XML文件存储的key-value键值对数据,通常用来存储一些简单的配置信息。通过DDMS的File Explorer面板,展开文件浏览树,很明显SharedPreferences数据总是存储在/data/data/<package name>/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过SharedPreferences.edit()获取的内部接口Editor对象实现。 SharedPreferences本身是一 个接口,程序无法直接创建SharedPreferences实例,只能通过Context提供的getSharedPreferences(String name, int mode)方法来获取SharedPreferences实例,该方法中name表示要操作的xml文件名,第二个参数具体如下: Context.MODE_PRIVATE: 指定该SharedPreferences数据只能被本应用程序读、写。 Context.MODE_WORLD_READABLE: 指定该SharedPreferences数据能被其他应用程序读,但不能写。 Context.MODE_WORLD_WRITEABLE: 指定该SharedPreferences数据能被其他应用程序读,写 Editor有如下主要重要方法: SharedPreferences.Editor clear():清空SharedPreferences里所有数据 SharedPreferences.Editor putXxx(String key , xxx value): 向SharedPreferences存入指定key对应的数据,其中xxx 可以是boolean,float,int等各种基本类型据 SharedPreferences.Editor remove(): 删除SharedPreferences中指定key对应的数据项 boolean commit(): 当Editor编辑完成后,使用该方法提交修改 实际案例:运行界面如下 这里只提供了两个按钮和一个输入文本框,布局简单,故在此不给出界面布局文件了,程序核心代码如下: 、class ViewOcl implements View.OnClickListener{ @Override public void onClick(View v) { switch(v.getId()){ case R.id.btnSet: //步骤1:获取输入值 String code = txtCode.getText().toString().trim(); //步骤2-1:创建一个SharedPreferences.Editor接口对象,lock表示要写入的XML文件名,MODE_WORLD_WRITEABLE写操作 SharedPreferences.Editor editor = getSharedPreferences("lock", MODE_WORLD_WRITEABLE).edit(); //步骤2-2:将获取过来的值放入文件 editor.putString("code", code); //步骤3:提交 editor.commit(); Toast.makeText(getApplicationContext(), "口令设置成功", Toast.LENGTH_LONG).show(); break; case R.id.btnGet: //步骤1:创建一个SharedPreferences接口对象 SharedPreferences read = getSharedPreferences("lock", MODE_WORLD_READABLE); //步骤2:获取文件中的值 String value = read.getString("code", ""); Toast.makeText(getApplicationContext(), "口令为:"+value, Toast.LENGTH_LONG).show(); break; } } } 、读写其他应用的SharedPreferences: 步骤如下 1、在创建SharedPreferences时,指定MODE_WORLD_READABLE模式,表明该SharedPreferences数据可以被其他程序读取 2、创建其他应用程序对应的Context: Context pvCount = createPackageContext("com.tony.app", Context.CONTEXT_IGNORE_SECURITY);这里的com.tony.app就是其他程序的包名 3、使用其他程序的Context获取对应的SharedPreferences SharedPreferences read = pvCount.getSharedPreferences("lock", Context.MODE_WORLD_READABLE); 4、如果是写入数据,使用Editor接口即可,所有其他操作均和前面一致。 SharedPreferences对象与SQLite数据库相比,免去了创建数据库,创建表,写SQL语句等诸多操作,相对而言更加方便,简洁。但是SharedPreferences也有其自身缺陷,比如其职能存储boolean,int,float,long和String五种简单的数据类型,比如其无法进行条件查询等。所以不论SharedPreferences的数据存储操作是如何简单,它也只能是存储方式的一种补充,而无法完全替代如SQLite数据库这样的其他数据存储方式。 第二种: 文件存储数据 核心原理: Context提供了两个方法来打开数据文件里的文件IO流 FileInputStream openFileInput(String name); FileOutputStream(String name , int mode),这两个方法第一个参数 用于指定文件名,第二个参数指定打开文件的模式。具体有以下值可选: MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,只能被应用本身访问,在该模式下,写入的内容会覆盖原文件的内容,如果想把新写入的内容追加到原文件中。可 以使用Context.MODE_APPEND MODE_APPEND:模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。 MODE_WORLD_READABLE:表示当前文件可以被其他应用读取; MODE_WORLD_WRITEABLE:表示当前文件可以被其他应用写入。 除此之外,Context还提供了如下几个重要的方法: getDir(String name , int mode):在应用程序的数据文件夹下获取或者创建name对应的子目录 File getFilesDir():获取该应用程序的数据文件夹得绝对路径 String[] fileList():返回该应用数据文件夹的全部文件 public String read() { try { FileInputStream inStream = this.openFileInput("message.txt"); byte[] buffer = new byte[1024]; int hasRead = 0; StringBuilder sb = new StringBuilder(); while ((hasRead = inStream.read(buffer)) != -1) { sb.append(new String(buffer, 0, hasRead)); } inStream.close(); return sb.toString(); } catch (Exception e) { e.printStackTrace(); } return null; } public void write(String msg){ // 步骤1:获取输入值 if(msg == null) return; try { // 步骤2:创建一个FileOutputStream对象,MODE_APPEND追加模式 FileOutputStream fos = openFileOutput("message.txt", MODE_APPEND); // 步骤3:将获取过来的值放入文件 fos.write(msg.getBytes()); // 步骤4:关闭数据流 fos.close(); } catch (Exception e) { e.printStackTrace(); } } openFileOutput()方法的第一参数用于指定文件名称,不能包含路径分隔符“/” ,如果文件不存在,Android 会自动创建它。创建的文件保存在/data/data//files目录,如: /data/data/cn.tony.app/files/message.txt, 下面讲解某些特殊文件读写需要注意的地方: 读写sdcard上的文件 其中读写步骤按如下进行: 1、调用Environment的getExternalStorageState()方法判断手机上是否插了sd卡,且应用程序具有读写SD卡的权限,如下代码将返回true Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED) 2、调用Environment.getExternalStorageDirectory()方法来获取外部存储器,也就是SD卡的目录,或者使用"/mnt/sdcard/"目录 3、使用IO流操作SD卡上的文件 注意点:手机应该已插入SD卡,对于模拟器而言,可通过mksdcard命令来创建虚拟存储卡 必须在AndroidManifest.xml上配置读写SD卡的权限 // 文件写操作函数 private void write(String content) { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定义File类对象 if (!file.getParentFile().exists()) { // 父文件夹不存在 file.getParentFile().mkdirs(); // 创建文件夹 } PrintStream out = null; // 打印流对象用于输出 try { out = new PrintStream(new FileOutputStream(file, true)); // 追加文件 out.println(content); } catch (Exception e) { e.printStackTrace(); } finally { if (out != null) { out.close(); // 关闭打印流 } } } else { // SDCard不存在,使用Toast提示用户 Toast.makeText(this, "保存失败,SD卡不存在!", Toast.LENGTH_LONG).show(); } } // 文件读操作函数 private String read() { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 如果sdcard存在 File file = new File(Environment.getExternalStorageDirectory() .toString() + File.separator + DIR + File.separator + FILENAME); // 定义File类对象 if (!file.getParentFile().exists()) { // 父文件夹不存在 file.getParentFile().mkdirs(); // 创建文件夹 } Scanner scan = null; // 扫描输入 StringBuilder sb = new StringBuilder(); try { scan = new Scanner(new FileInputStream(file)); // 实例化Scanner while (scan.hasNext()) { // 循环读取 sb.append(scan.next() + "\n"); // 设置文本 } return sb.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if (scan != null) { scan.close(); // 关闭打印流 } } } else { // SDCard不存在,使用Toast提示用户 Toast.makeText(this, "读取失败,SD卡不存在!", Toast.LENGTH_LONG).show(); } return null; } 复制代码 第三种:SQLite存储数据 SQLite是轻量级嵌入式数据库引擎,它支持 SQL 语言,并且只利用很少的内存就有很好的性能。现在的主流移动设备像Android、iPhone等都使用SQLite作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到SQLite来存储我们大量的数据,所以我们就需要掌握移动设备上的SQLite开发技巧 SQLiteDatabase类为我们提供了很多种方法,上面的代码中基本上囊括了大部分的数据库操作;对于添加、更新和删除来说,我们都可以使用 1 db.executeSQL(String sql); 2 db.executeSQL(String sql, Object[] bindArgs);//sql语句中使用占位符,然后第二个参数是实际的参数集 除了统一的形式之外,他们还有各自的操作方法: 1 db.insert(String table, String nullColumnHack, ContentValues values); 2 db.update(String table, Contentvalues values, String whereClause, String whereArgs); 3 db.delete(String table, String whereClause, String whereArgs);以上三个方法的第一个参数都是表示要操作的表名;insert中的第二个参数表示如果插入的数据每一列都为空的话,需要指定此行中某一列的名称,系统将此列设置为NULL,不至于出现错误;insert中的第三个参数是ContentValues类型的变量,是键值对组成的Map,key代表列名,value代表该列要插入的值;update的第二个参数也很类似,只不过它是更新该字段key为最新的value值,第三个参数whereClause表示WHERE表达式,比如“age > ? and age < ?”等,最后的whereArgs参数是占位符的实际参数值;delete方法的参数也是一样 下面给出demo 数据的添加 1.使用insert方法 复制代码1 ContentValues cv = new ContentValues();//实例化一个ContentValues用来装载待插入的数据2 cv.put("title","you are beautiful");//添加title3 cv.put("weather","sun"); //添加weather4 cv.put("context","xxxx"); //添加context5 String publish = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")6 .format(new Date());7 cv.put("publish ",publish); //添加publish8 db.insert("diary",null,cv);//执行插入操作复制代码2.使用execSQL方式来实现 String sql = "insert into user(username,password) values ('Jack Johnson','iLovePopMuisc');//插入操作的SQL语句db.execSQL(sql);//执行SQL语句数据的删除 同样有2种方式可以实现 String whereClause = "username=?";//删除的条件String[] whereArgs = {"Jack Johnson"};//删除的条件参数db.delete("user",whereClause,whereArgs);//执行删除使用execSQL方式的实现 String sql = "delete from user where username='Jack Johnson'";//删除操作的SQL语句db.execSQL(sql);//执行删除操作数据修改 同上,仍是2种方式 ContentValues cv = new ContentValues();//实例化ContentValuescv.put("password","iHatePopMusic");//添加要更改的字段及内容String whereClause = "username=?";//修改条件String[] whereArgs = {"Jack Johnson"};//修改条件的参数db.update("user",cv,whereClause,whereArgs);//执行修改使用execSQL方式的实现 String sql = "update user set password = 'iHatePopMusic' where username='Jack Johnson'";//修改的SQL语句db.execSQL(sql);//执行修改数据查询 下面来说说查询操作。查询操作相对于上面的几种操作要复杂些,因为我们经常要面对着各种各样的查询条件,所以系统也考虑到这种复杂性,为我们提供了较为丰富的查询形式: 1 db.rawQuery(String sql, String[] selectionArgs); 2 db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy); 3 db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit); 4 db.query(String distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit); 上面几种都是常用的查询方法,第一种最为简单,将所有的SQL语句都组织到一个字符串中,使用占位符代替实际参数,selectionArgs就是占位符实际参数集; 各参数说明: table:表名称colums:表示要查询的列所有名称集selection:表示WHERE之后的条件语句,可以使用占位符selectionArgs:条件语句的参数数组groupBy:指定分组的列名having:指定分组条件,配合groupBy使用orderBy:y指定排序的列名limit:指定分页参数distinct:指定“true”或“false”表示要不要过滤重复值Cursor:返回值,相当于结果集ResultSet最后,他们同时返回一个Cursor对象,代表数据集的游标,有点类似于JavaSE中的ResultSet。下面是Cursor对象的常用方法: 复制代码 1 c.move(int offset); //以当前位置为参考,移动到指定行 2 c.moveToFirst(); //移动到第一行 3 c.moveToLast(); //移动到最后一行 4 c.moveToPosition(int position); //移动到指定行 5 c.moveToPrevious(); //移动到前一行 6 c.moveToNext(); //移动到下一行 7 c.isFirst(); //是否指向第一条 8 c.isLast(); //是否指向最后一条 9 c.isBeforeFirst(); //是否指向第一条之前 10 c.isAfterLast(); //是否指向最后一条之后 11 c.isNull(int columnIndex); //指定列是否为空(列基数为0) 12 c.isClosed(); //游标是否已关闭 13 c.getCount(); //总数据项数 14 c.getPosition(); //返回当前游标所指向的行数 15 c.getColumnIndex(String columnName);//返回某列名对应的列索引值 16 c.getString(int columnIndex); //返回当前行指定列的值 复制代码实现代码 复制代码String[] params = {12345,123456};Cursor cursor = db.query("user",columns,"ID=?",params,null,null,null);//查询并获得游标if(cursor.moveToFirst()){//判断游标是否为空 for(int i=0;i<cursor.getCount();i++){ cursor.move(i);//移动到指定记录 String username = cursor.getString(cursor.getColumnIndex("username"); String password = cursor.getString(cursor.getColumnIndex("password")); } }复制代码通过rawQuery实现的带参数查询 复制代码Cursor result=db.rawQuery("SELECT ID, name, inventory FROM mytable");//Cursor c = db.rawQuery("s name, inventory FROM mytable where ID=?",new Stirng[]{"123456"}); result.moveToFirst(); while (!result.isAfterLast()) { int id=result.getInt(0); String name=result.getString(1); int inventory=result.getInt(2); // do something useful with these result.moveToNext(); } result.close();复制代码 在上面的代码示例中,已经用到了这几个常用方法中的一些,关于更多的信息,大家可以参考官方文档中的说明。 最后当我们完成了对数据库的操作后,记得调用SQLiteDatabase的close()方法释放数据库连接,否则容易出现SQLiteException。 上面就是SQLite的基本应用,但在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自SQLiteOpenHelper类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。 这里直接使用案例讲解:下面是案例demo的界面 SQLiteOpenHelper类介绍 SQLiteOpenHelper是SQLiteDatabase的一个帮助类,用来管理数据库的创建和版本的更新。一般是建立一个类继承它,并实现它的onCreate和onUpgrade方法。 方法名 方法描述SQLiteOpenHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version) 构造方法,其中 context 程序上下文环境 即:XXXActivity.this; name :数据库名字; factory:游标工厂,默认为null,即为使用默认工厂; version 数据库版本号 onCreate(SQLiteDatabase db) 创建数据库时调用onUpgrade(SQLiteDatabase db,int oldVersion , int newVersion) 版本更新时调用getReadableDatabase() 创建或打开一个只读数据库getWritableDatabase() 创建或打开一个读写数据库首先创建数据库类 复制代码 1 import android.content.Context; 2 import android.database.sqlite.SQLiteDatabase; 3 import android.database.sqlite.SQLiteDatabase.CursorFactory; 4 import android.database.sqlite.SQLiteOpenHelper; 5 6 public class SqliteDBHelper extends SQLiteOpenHelper { 7 8 // 步骤1:设置常数参量 9 private static final String DATABASE_NAME = "diary_db";10 private static final int VERSION = 1;11 private static final String TABLE_NAME = "diary";12 13 // 步骤2:重载构造方法14 public SqliteDBHelper(Context context) {15 super(context, DATABASE_NAME, null, VERSION);16 }17 18 /*19 * 参数介绍:context 程序上下文环境 即:XXXActivity.this 20 * name 数据库名字 21 * factory 接收数据,一般情况为null22 * version 数据库版本号23 */24 public SqliteDBHelper(Context context, String name, CursorFactory factory,25 int version) {26 super(context, name, factory, version);27 }28 //数据库第一次被创建时,onCreate()会被调用29 @Override30 public void onCreate(SQLiteDatabase db) {31 // 步骤3:数据库表的创建32 String strSQL = "create table "33 + TABLE_NAME34 + "(tid integer primary key autoincrement,title varchar(20),weather varchar(10),context text,publish date)";35 //步骤4:使用参数db,创建对象36 db.execSQL(strSQL);37 }38 //数据库版本变化时,会调用onUpgrade()39 @Override40 public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {41 42 }43 }复制代码正如上面所述,数据库第一次创建时onCreate方法会被调用,我们可以执行创建表的语句,当系统发现版本变化之后,会调用onUpgrade方法,我们可以执行修改表结构等语句。 我们需要一个Dao,来封装我们所有的业务方法,代码如下: 复制代码 1 import android.content.Context; 2 import android.database.Cursor; 3 import android.database.sqlite.SQLiteDatabase; 4 5 import com.chinasoft.dbhelper.SqliteDBHelper; 6 7 public class DiaryDao { 8 9 private SqliteDBHelper sqliteDBHelper;10 private SQLiteDatabase db;11 12 // 重写构造方法13 public DiaryDao(Context context) {14 this.sqliteDBHelper = new SqliteDBHelper(context);15 db = sqliteDBHelper.getWritableDatabase();16 }17 18 // 读操作19 public String execQuery(final String strSQL) {20 try {21 System.out.println("strSQL>" + strSQL);22 // Cursor相当于JDBC中的ResultSet23 Cursor cursor = db.rawQuery(strSQL, null);24 // 始终让cursor指向数据库表的第1行记录25 cursor.moveToFirst();26 // 定义一个StringBuffer的对象,用于动态拼接字符串27 StringBuffer sb = new StringBuffer();28 // 循环游标,如果不是最后一项记录29 while (!cursor.isAfterLast()) {30 sb.append(cursor.getInt(0) + "/" + cursor.getString(1) + "/"31 + cursor.getString(2) + "/" + cursor.getString(3) + "/"32 + cursor.getString(4)+"#");33 //cursor游标移动34 cursor.moveToNext();35 }36 db.close();37 return sb.deleteCharAt(sb.length()-1).toString();38 } catch (RuntimeException e) {39 e.printStackTrace();40 return null;41 }42 43 }44 45 // 写操作46 public boolean execOther(final String strSQL) {47 db.beginTransaction(); //开始事务48 try {49 System.out.println("strSQL" + strSQL);50 db.execSQL(strSQL);51 db.setTransactionSuccessful(); //设置事务成功完成 52 db.close();53 return true;54 } catch (RuntimeException e) {55 e.printStackTrace();56 return false;57 }finally { 58 db.endTransaction(); //结束事务 59 } 60 61 }62 }复制代码我们在Dao构造方法中实例化sqliteDBHelper并获取一个SQLiteDatabase对象,作为整个应用的数据库实例;在增删改信息时,我们采用了事务处理,确保数据完整性;最后要注意释放数据库资源db.close(),这一个步骤在我们整个应用关闭时执行,这个环节容易被忘记,所以朋友们要注意。 我们获取数据库实例时使用了getWritableDatabase()方法,也许朋友们会有疑问,在getWritableDatabase()和getReadableDatabase()中,你为什么选择前者作为整个应用的数据库实例呢?在这里我想和大家着重分析一下这一点。 我们来看一下SQLiteOpenHelper中的getReadableDatabase()方法: 复制代码 1 public synchronized SQLiteDatabase getReadableDatabase() { 2 if (mDatabase != null && mDatabase.isOpen()) { 3 // 如果发现mDatabase不为空并且已经打开则直接返回 4 return mDatabase; 5 } 6 7 if (mIsInitializing) { 8 // 如果正在初始化则抛出异常 9 throw new IllegalStateException("getReadableDatabase called recursively"); 10 } 11 12 // 开始实例化数据库mDatabase 13 14 try { 15 // 注意这里是调用了getWritableDatabase()方法 16 return getWritableDatabase(); 17 } catch (SQLiteException e) { 18 if (mName == null) 19 throw e; // Can't open a temp database read-only! 20 Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", e); 21 } 22 23 // 如果无法以可读写模式打开数据库 则以只读方式打开 24 25 SQLiteDatabase db = null; 26 try { 27 mIsInitializing = true; 28 String path = mContext.getDatabasePath(mName).getPath();// 获取数据库路径 29 // 以只读方式打开数据库 30 db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY); 31 if (db.getVersion() != mNewVersion) { 32 throw new SQLiteException("Can't upgrade read-only database from version " + db.getVersion() + " to " 33 + mNewVersion + ": " + path); 34 } 35 36 onOpen(db); 37 Log.w(TAG, "Opened " + mName + " in read-only mode"); 38 mDatabase = db;// 为mDatabase指定新打开的数据库 39 return mDatabase;// 返回打开的数据库 40 } finally { 41 mIsInitializing = false; 42 if (db != null && db != mDatabase) 43 db.close(); 44 } 45 }复制代码在getReadableDatabase()方法中,首先判断是否已存在数据库实例并且是打开状态,如果是,则直接返回该实例,否则试图获取一个可读写模式的数据库实例,如果遇到磁盘空间已满等情况获取失败的话,再以只读模式打开数据库,获取数据库实例并返回,然后为mDatabase赋值为最新打开的数据库实例。既然有可能调用到getWritableDatabase()方法,我们就要看一下了: 复制代码public synchronized SQLiteDatabase getWritableDatabase() { if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) { // 如果mDatabase不为空已打开并且不是只读模式 则返回该实例 return mDatabase; } if (mIsInitializing) { throw new IllegalStateException("getWritableDatabase called recursively"); } // If we have a read-only database open, someone could be using it // (though they shouldn't), which would cause a lock to be held on // the file, and our attempts to open the database read-write would // fail waiting for the file lock. To prevent that, we acquire the // lock on the read-only database, which shuts out other users. boolean success = false; SQLiteDatabase db = null; // 如果mDatabase不为空则加锁 阻止其他的操作 if (mDatabase != null) mDatabase.lock(); try { mIsInitializing = true; if (mName == null) { db = SQLiteDatabase.create(null); } else { // 打开或创建数据库 db = mContext.openOrCreateDatabase(mName, 0, mFactory); } // 获取数据库版本(如果刚创建的数据库,版本为0) int version = db.getVersion(); // 比较版本(我们代码中的版本mNewVersion为1) if (version != mNewVersion) { db.beginTransaction();// 开始事务 try { if (version == 0) { // 执行我们的onCreate方法 onCreate(db); } else { // 如果我们应用升级了mNewVersion为2,而原版本为1则执行onUpgrade方法 onUpgrade(db, version, mNewVersion); } db.setVersion(mNewVersion);// 设置最新版本 db.setTransactionSuccessful();// 设置事务成功 } finally { db.endTransaction();// 结束事务 } } onOpen(db); success = true; return db;// 返回可读写模式的数据库实例 } finally { mIsInitializing = false; if (success) { // 打开成功 if (mDatabase != null) { // 如果mDatabase有值则先关闭 try { mDatabase.close(); } catch (Exception e) { } mDatabase.unlock();// 解锁 } mDatabase = db;// 赋值给mDatabase } else { // 打开失败的情况:解锁、关闭 if (mDatabase != null) mDatabase.unlock(); if (db != null) db.close(); } } }复制代码大家可以看到,几个关键步骤是,首先判断mDatabase如果不为空已打开并不是只读模式则直接返回,否则如果mDatabase不为空则加锁,然后开始打开或创建数据库,比较版本,根据版本号来调用相应的方法,为数据库设置新版本号,最后释放旧的不为空的mDatabase并解锁,把新打开的数据库实例赋予mDatabase,并返回最新实例。 看完上面的过程之后,大家或许就清楚了许多,如果不是在遇到磁盘空间已满等情况,getReadableDatabase()一般都会返回和getWritableDatabase()一样的数据库实例,所以我们在DBManager构造方法中使用getWritableDatabase()获取整个应用所使用的数据库实例是可行的。当然如果你真的担心这种情况会发生,那么你可以先用getWritableDatabase()获取数据实例,如果遇到异常,再试图用getReadableDatabase()获取实例,当然这个时候你获取的实例只能读不能写了 最后,让我们看一下如何使用这些数据操作方法来显示数据,界面核心逻辑代码: 复制代码public class SQLiteActivity extends Activity { public DiaryDao diaryDao; //因为getWritableDatabase内部调用了mContext.openOrCreateDatabase(mName, 0, mFactory); //所以要确保context已初始化,我们可以把实例化Dao的步骤放在Activity的onCreate里 @Override protected void onCreate(Bundle savedInstanceState) { diaryDao = new DiaryDao(SQLiteActivity.this); initDatabase(); } class ViewOcl implements View.OnClickListener { @Override public void onClick(View v) { String strSQL; boolean flag; String message; switch (v.getId()) { case R.id.btnAdd: String title = txtTitle.getText().toString().trim(); String weather = txtWeather.getText().toString().trim();; String context = txtContext.getText().toString().trim();; String publish = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") .format(new Date()); // 动态组件SQL语句 strSQL = "insert into diary values(null,'" + title + "','" + weather + "','" + context + "','" + publish + "')"; flag = diaryDao.execOther(strSQL); //返回信息 message = flag?"添加成功":"添加失败"; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); break; case R.id.btnDelete: strSQL = "delete from diary where tid = 1"; flag = diaryDao.execOther(strSQL); //返回信息 message = flag?"删除成功":"删除失败"; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); break; case R.id.btnQuery: strSQL = "select * from diary order by publish desc"; String data = diaryDao.execQuery(strSQL); Toast.makeText(getApplicationContext(), data, Toast.LENGTH_LONG).show(); break; case R.id.btnUpdate: strSQL = "update diary set title = '测试标题1-1' where tid = 1"; flag = diaryDao.execOther(strSQL); //返回信息 message = flag?"更新成功":"更新失败"; Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show(); break; } } } private void initDatabase() { // 创建数据库对象 SqliteDBHelper sqliteDBHelper = new SqliteDBHelper(SQLiteActivity.this); sqliteDBHelper.getWritableDatabase(); System.out.println("数据库创建成功"); } }复制代码 Android sqlite3数据库管理工具 Android SDK的tools目录下提供了一个sqlite3.exe工具,这是一个简单的sqlite数据库管理工具。开发者可以方便的使用其对sqlite数据库进行命令行的操作。 程序运行生成的.db文件一般位于"/data/data/项目名(包括所处包名)/databases/.db",因此要对数据库文件进行操作需要先找到数据库文件: 1、进入shell 命令 adb shell2、找到数据库文件 cd data/data ls --列出所有项目 cd project_name --进入所需项目名 cd databases ls --列出现寸的数据库文件 3、进入数据库 sqlite3 test_db --进入所需数据库 会出现类似如下字样: SQLite version 3.6.22Enter ".help" for instructionsEnter SQL statements terminated with a ";"sqlite>至此,可对数据库进行sql操作。 4、sqlite常用命令 .databases --产看当前数据库.tables --查看当前数据库中的表.help --sqlite3帮助.schema --各个表的生成语句 原文地址https://www.cnblogs.com/ITtangtang/p/3920916.html

auto_answer 2019-12-02 01:50:21 0 浏览量 回答数 0

回答

如果树不是太大,则可以使用一些聪明的引用在PHP中构建树。 $nodeList = array(); $tree = array(); $query = mysql_query("SELECT category_id, name, parent FROM categories ORDER BY parent"); while($row = mysql_fetch_assoc($query)){ $nodeList[$row['category_id']] = array_merge($row, array('children' => array())); } mysql_free_result($query); foreach ($nodeList as $nodeId => &$node) { if (!$node['parent'] || !array_key_exists($node['parent'], $nodeList)) { $tree[] = &$node; } else { $nodeList[$node['parent']]['children'][] = &$node; } } unset($node); unset($nodeList); 这将为您$tree提供带有相应children-slot 子级的树结构。 我们已经用相当大的树(> 1000项)完成了此操作,它非常稳定并且比在MySQL中进行递归查询要快得多。来源:stack overflow

保持可爱mmm 2020-05-17 21:32:26 0 浏览量 回答数 0

回答

92题 一般来说,建立INDEX有以下益处:提高查询效率;建立唯一索引以保证数据的唯一性;设计INDEX避免排序。 缺点,INDEX的维护有以下开销:叶节点的‘分裂’消耗;INSERT、DELETE和UPDATE操作在INDEX上的维护开销;有存储要求;其他日常维护的消耗:对恢复的影响,重组的影响。 需要建立索引的情况:为了建立分区数据库的PATITION INDEX必须建立; 为了保证数据约束性需要而建立的INDEX必须建立; 为了提高查询效率,则考虑建立(是否建立要考虑相关性能及维护开销); 考虑在使用UNION,DISTINCT,GROUP BY,ORDER BY等字句的列上加索引。 91题 作用:加快查询速度。原则:(1) 如果某属性或属性组经常出现在查询条件中,考虑为该属性或属性组建立索引;(2) 如果某个属性常作为最大值和最小值等聚集函数的参数,考虑为该属性建立索引;(3) 如果某属性经常出现在连接操作的连接条件中,考虑为该属性或属性组建立索引。 90题 快照Snapshot是一个文件系统在特定时间里的镜像,对于在线实时数据备份非常有用。快照对于拥有不能停止的应用或具有常打开文件的文件系统的备份非常重要。对于只能提供一个非常短的备份时间而言,快照能保证系统的完整性。 89题 游标用于定位结果集的行,通过判断全局变量@@FETCH_STATUS可以判断是否到了最后,通常此变量不等于0表示出错或到了最后。 88题 事前触发器运行于触发事件发生之前,而事后触发器运行于触发事件发生之后。通常事前触发器可以获取事件之前和新的字段值。语句级触发器可以在语句执行前或后执行,而行级触发在触发器所影响的每一行触发一次。 87题 MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。具体原因为:MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。 86题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 85题 存储过程是一组Transact-SQL语句,在一次编译后可以执行多次。因为不必重新编译Transact-SQL语句,所以执行存储过程可以提高性能。触发器是一种特殊类型的存储过程,不由用户直接调用。创建触发器时会对其进行定义,以便在对特定表或列作特定类型的数据修改时执行。 84题 存储过程是用户定义的一系列SQL语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表。 83题 减少表连接,减少复杂 SQL,拆分成简单SQL。减少排序:非必要不排序,利用索引排序,减少参与排序的记录数。尽量避免 select *。尽量用 join 代替子查询。尽量少使用 or,使用 in 或者 union(union all) 代替。尽量用 union all 代替 union。尽量早的将无用数据过滤:选择更优的索引,先分页再Join…。避免类型转换:索引失效。优先优化高并发的 SQL,而不是执行频率低某些“大”SQL。从全局出发优化,而不是片面调整。尽可能对每一条SQL进行 explain。 82题 如果条件中有or,即使其中有条件带索引也不会使用(要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引)。对于多列索引,不是使用的第一部分,则不会使用索引。like查询是以%开头。如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引。如果mysql估计使用全表扫描要比使用索引快,则不使用索引。例如,使用<>、not in 、not exist,对于这三种情况大多数情况下认为结果集很大,MySQL就有可能不使用索引。 81题 主键不能重复,不能为空,唯一键不能重复,可以为空。建立主键的目的是让外键来引用。一个表最多只有一个主键,但可以有很多唯一键。 80题 空值('')是不占用空间的,判断空字符用=''或者<>''来进行处理。NULL值是未知的,且占用空间,不走索引;判断 NULL 用 IS NULL 或者 is not null ,SQL 语句函数中可以使用 ifnull ()函数来进行处理。无法比较 NULL 和 0;它们是不等价的。无法使用比较运算符来测试 NULL 值,比如 =, <, 或者 <>。NULL 值可以使用 <=> 符号进行比较,该符号与等号作用相似,但对NULL有意义。进行 count ()统计某列的记录数的时候,如果采用的 NULL 值,会被系统自动忽略掉,但是空值是统计到其中。 79题 HEAP表是访问数据速度最快的MySQL表,他使用保存在内存中的散列索引。一旦服务器重启,所有heap表数据丢失。BLOB或TEXT字段是不允许的。只能使用比较运算符=,<,>,=>,= <。HEAP表不支持AUTO_INCREMENT。索引不可为NULL。 78题 如果想输入字符为十六进制数字,可以输入带有单引号的十六进制数字和前缀(X),或者只用(Ox)前缀输入十六进制数字。如果表达式上下文是字符串,则十六进制数字串将自动转换为字符串。 77题 Mysql服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。 76题 在缺省模式下,MYSQL是autocommit模式的,所有的数据库更新操作都会即时提交,所以在缺省情况下,mysql是不支持事务的。但是如果你的MYSQL表类型是使用InnoDB Tables 或 BDB tables的话,你的MYSQL就可以使用事务处理,使用SET AUTOCOMMIT=0就可以使MYSQL允许在非autocommit模式,在非autocommit模式下,你必须使用COMMIT来提交你的更改,或者用ROLLBACK来回滚你的更改。 75题 它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。 74题 创建索引的时候尽量使用唯一性大的列来创建索引,由于使用b+tree做为索引,以innodb为例,一个树节点的大小由“innodb_page_size”,为了减少树的高度,同时让一个节点能存放更多的值,索引列尽量在整数类型上创建,如果必须使用字符类型,也应该使用长度较少的字符类型。 73题 当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下: 限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读。垂直分区: 根据数据库里面数据表的相关性进行拆分。简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。水平分区: 保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。水平拆分可以支撑非常大的数据量。 72题 乐观锁失败后会抛出ObjectOptimisticLockingFailureException,那么我们就针对这块考虑一下重试,自定义一个注解,用于做切面。针对注解进行切面,设置最大重试次数n,然后超过n次后就不再重试。 71题 一致性非锁定读讲的是一条记录被加了X锁其他事务仍然可以读而不被阻塞,是通过innodb的行多版本实现的,行多版本并不是实际存储多个版本记录而是通过undo实现(undo日志用来记录数据修改前的版本,回滚时会用到,用来保证事务的原子性)。一致性锁定读讲的是我可以通过SELECT语句显式地给一条记录加X锁从而保证特定应用场景下的数据一致性。 70题 数据库引擎:尤其是mysql数据库只有是InnoDB引擎的时候事物才能生效。 show engines 查看数据库默认引擎;SHOW TABLE STATUS from 数据库名字 where Name='表名' 如下;SHOW TABLE STATUS from rrz where Name='rrz_cust';修改表的引擎alter table table_name engine=innodb。 69题 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);哈希索引也不支持多列联合索引的最左匹配规则;B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。 68题 decimal精度比float高,数据处理比float简单,一般优先考虑,但float存储的数据范围大,所以范围大的数据就只能用它了,但要注意一些处理细节,因为不精确可能会与自己想的不一致,也常有关于float 出错的问题。 67题 datetime、timestamp精确度都是秒,datetime与时区无关,存储的范围广(1001-9999),timestamp与时区有关,存储的范围小(1970-2038)。 66题 Char使用固定长度的空间进行存储,char(4)存储4个字符,根据编码方式的不同占用不同的字节,gbk编码方式,不论是中文还是英文,每个字符占用2个字节的空间,utf8编码方式,每个字符占用3个字节的空间。Varchar保存可变长度的字符串,使用额外的一个或两个字节存储字符串长度,varchar(10),除了需要存储10个字符,还需要1个字节存储长度信息(10),超过255的长度需要2个字节来存储。char和varchar后面如果有空格,char会自动去掉空格后存储,varchar虽然不会去掉空格,但在进行字符串比较时,会去掉空格进行比较。Varbinary保存变长的字符串,后面不会补\0。 65题 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。 64题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 63题 存储过程是一些预编译的SQL语句。1、更加直白的理解:存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。2、存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全。 62题 密码散列、盐、用户身份证号等固定长度的字符串应该使用char而不是varchar来存储,这样可以节省空间且提高检索效率。 61题 推荐使用自增ID,不要使用UUID。因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。总之,在数据量大一些的情况下,用自增主键性能会好一些。 60题 char是一个定长字段,假如申请了char(10)的空间,那么无论实际存储多少内容。该字段都占用10个字符,而varchar是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度+1,最后一个字符存储使用了多长的空间。在检索效率上来讲,char > varchar,因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar。例如存储用户MD5加密后的密码,则应该使用char。 59题 一. read uncommitted(读取未提交数据) 即便是事务没有commit,但是我们仍然能读到未提交的数据,这是所有隔离级别中最低的一种。 二. read committed(可以读取其他事务提交的数据)---大多数数据库默认的隔离级别 当前会话只能读取到其他事务提交的数据,未提交的数据读不到。 三. repeatable read(可重读)---MySQL默认的隔离级别 当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。 四. serializable(串行化) 其他会话对该表的写操作将被挂起。可以看到,这是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。 58题 B+树的高度一般为2-4层,所以查找记录时最多只需要2-4次IO,相对二叉平衡树已经大大降低了。范围查找时,能通过叶子节点的指针获取数据。例如查找大于等于3的数据,当在叶子节点中查到3时,通过3的尾指针便能获取所有数据,而不需要再像二叉树一样再获取到3的父节点。 57题 因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。 56题 redo log是物理日志,记录的是"在某个数据页上做了什么修改"。 binlog是逻辑日志,记录的是这个语句的原始逻辑,比如"给ID=2这一行的c字段加1"。 redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。 redo log是循环写的,空间固定会用完:binlog 是可以追加写入的。"追加写"是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。 最开始 MySQL 里并没有 InnoDB 引擎,MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog日志只能用于归档。而InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统,也就是 redo log 来实现 crash-safe 能力。 55题 重做日志(redo log)      作用:确保事务的持久性,防止在发生故障,脏页未写入磁盘。重启数据库会进行redo log执行重做,达到事务一致性。 回滚日志(undo log)  作用:保证数据的原子性,保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。 二进 制日志(binlog)    作用:用于主从复制,实现主从同步;用于数据库的基于时间点的还原。 错误日志(errorlog) 作用:Mysql本身启动,停止,运行期间发生的错误信息。 慢查询日志(slow query log)  作用:记录执行时间过长的sql,时间阈值可以配置,只记录执行成功。 一般查询日志(general log)    作用:记录数据库的操作明细,默认关闭,开启后会降低数据库性能 。 中继日志(relay log) 作用:用于数据库主从同步,将主库发来的bin log保存在本地,然后从库进行回放。 54题 MySQL有三种锁的级别:页级、表级、行级。 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。 死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。 那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。死锁的解决办法:1.查出的线程杀死。2.设置锁的超时时间。3.指定获取锁的顺序。 53题 当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性(脏读,不可重复读,幻读等),可能产生死锁。 乐观锁:乐观锁不是数据库自带的,需要我们自己去实现。 悲观锁:在进行每次操作时都要通过获取锁才能进行对相同数据的操作。 共享锁:加了共享锁的数据对象可以被其他事务读取,但不能修改。 排他锁:当数据对象被加上排它锁时,一个事务必须得到锁才能对该数据对象进行访问,一直到事务结束锁才被释放。 行锁:就是给某一条记录加上锁。 52题 Mysql是关系型数据库,MongoDB是非关系型数据库,数据存储结构的不同。 51题 关系型数据库优点:1.保持数据的一致性(事务处理)。 2.由于以标准化为前提,数据更新的开销很小。 3. 可以进行Join等复杂查询。 缺点:1、为了维护一致性所付出的巨大代价就是其读写性能比较差。 2、固定的表结构。 3、高并发读写需求。 4、海量数据的高效率读写。 非关系型数据库优点:1、无需经过sql层的解析,读写性能很高。 2、基于键值对,数据没有耦合性,容易扩展。 3、存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,而关系型数据库则只支持基础类型。 缺点:1、不提供sql支持,学习和使用成本较高。 2、无事务处理,附加功能bi和报表等支持也不好。 redis与mongoDB的区别: 性能:TPS方面redis要大于mongodb。 可操作性:mongodb支持丰富的数据表达,索引,redis较少的网络IO次数。 可用性:MongoDB优于Redis。 一致性:redis事务支持比较弱,mongoDB不支持事务。 数据分析:mongoDB内置了数据分析的功能(mapreduce)。 应用场景:redis数据量较小的更性能操作和运算上,MongoDB主要解决海量数据的访问效率问题。 50题 如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。 49题 分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。 48题 除了缓存服务器自带的缓存失效策略之外(Redis默认的有6种策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种: 1.定时去清理过期的缓存; 2.当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。 两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,可以根据应用场景来权衡。 47题 Redis提供了两种方式来作消息队列: 一个是使用生产者消费模式模式:会让一个或者多个客户端监听消息队列,一旦消息到达,消费者马上消费,谁先抢到算谁的,如果队列里没有消息,则消费者继续监听 。另一个就是发布订阅者模式:也是一个或多个客户端订阅消息频道,只要发布者发布消息,所有订阅者都能收到消息,订阅者都是平等的。 46题 Redis的数据结构列表(list)可以实现延时队列,可以通过队列和栈来实现。blpop/brpop来替换lpop/rpop,blpop/brpop阻塞读在队列没有数据的时候,会立即进入休眠状态,一旦数据到来,则立刻醒过来。Redis的有序集合(zset)可以用于实现延时队列,消息作为value,时间作为score。Zrem 命令用于移除有序集中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集类型时,返回一个错误。 45题 1.热点数据缓存:因为Redis 访问速度块、支持的数据类型比较丰富。 2.限时业务:expire 命令设置 key 的生存时间,到时间后自动删除 key。 3.计数器:incrby 命令可以实现原子性的递增。 4.排行榜:借助 SortedSet 进行热点数据的排序。 5.分布式锁:利用 Redis 的 setnx 命令进行。 6.队列机制:有 list push 和 list pop 这样的命令。 44题 一致哈希 是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只需要对 K/n 个关键字重新映射,其中K是关键字的数量, n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。 43题 RDB的优点:适合做冷备份;读写服务影响小,reids可以保持高性能;重启和恢复redis进程,更加快速。RDB的缺点:宕机会丢失最近5分钟的数据;文件特别大时可能会暂停数毫秒,或者甚至数秒。 AOF的优点:每个一秒执行fsync操作,最多丢失1秒钟的数据;以append-only模式写入,没有任何磁盘寻址的开销;文件过大时,不会影响客户端读写;适合做灾难性的误删除的紧急恢复。AOF的缺点:AOF日志文件比RDB数据快照文件更大,支持写QPS比RDB支持的写QPS低;比RDB脆弱,容易有bug。 42题 对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。Redis的操作之所以是原子性的,是因为Redis是单线程的。而在程序中执行多个Redis命令并非是原子性的,这也和普通数据库的表现是一样的,可以用incr或者使用Redis的事务,或者使用Redis+Lua的方式实现。对Redis来说,执行get、set以及eval等API,都是一个一个的任务,这些任务都会由Redis的线程去负责执行,任务要么执行成功,要么执行失败,这就是Redis的命令是原子性的原因。 41题 (1)twemproxy,使用方式简单(相对redis只需修改连接端口),对旧项目扩展的首选。(2)codis,目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在节点数改变情况下,旧节点数据可恢复到新hash节点。(3)redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持节点设置从节点。(4)在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key进行hash计算,然后去对应的redis实例操作数据。这种方式对hash层代码要求比较高,考虑部分包括,节点失效后的代替算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。 40题 (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件 (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次 (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内 (4) 尽量避免在压力很大的主库上增加从库 (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。 39题 比如订单管理,热数据:3个月内的订单数据,查询实时性较高;温数据:3个月 ~ 12个月前的订单数据,查询频率不高;冷数据:1年前的订单数据,几乎不会查询,只有偶尔的查询需求。热数据使用mysql进行存储,需要分库分表;温数据可以存储在ES中,利用搜索引擎的特性基本上也可以做到比较快的查询;冷数据可以存放到Hive中。从存储形式来说,一般情况冷数据存储在磁带、光盘,热数据一般存放在SSD中,存取速度快,而温数据可以存放在7200转的硬盘。 38题 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。 37题 分层架构设计,有一条准则:站点层、服务层要做到无数据无状态,这样才能任意的加节点水平扩展,数据和状态尽量存储到后端的数据存储服务,例如数据库服务或者缓存服务。显然进程内缓存违背了这一原则。 36题 更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个 jvm 内部队列中。读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个 jvm 内部队列中。一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行。 35题 redis分布式锁加锁过程:通过setnx向特定的key写入一个随机值,并同时设置失效时间,写值成功既加锁成功;redis分布式锁解锁过程:匹配随机值,删除redis上的特点key数据,要保证获取数据、判断一致以及删除数据三个操作是原子的,为保证原子性一般使用lua脚本实现;在此基础上进一步优化的话,考虑使用心跳检测对锁的有效期进行续期,同时基于redis的发布订阅优雅的实现阻塞式加锁。 34题 volatile-lru:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。 volatile-ttl:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选将要过期的数据淘汰。 volatile-random:当内存不足以容纳写入数据时,从已设置过期时间的数据集中任意选择数据淘汰。 allkeys-lru:当内存不足以容纳写入数据时,从数据集中挑选最近最少使用的数据淘汰。 allkeys-random:当内存不足以容纳写入数据时,从数据集中任意选择数据淘汰。 noeviction:禁止驱逐数据,当内存使用达到阈值的时候,所有引起申请内存的命令会报错。 33题 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。 32题 缓存击穿,一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。如何避免:在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。 31题 缓存雪崩,是指在某一个时间段,缓存集中过期失效。大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。而缓存服务器某个节点宕机或断网,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。如何避免:1.redis高可用,搭建redis集群。2.限流降级,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。3.数据预热,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间。 30题 缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。一些恶意的请求会故意查询不存在的 key,请求量很大,对数据库造成压力,甚至压垮数据库。 如何避免:1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 了之后清理缓存。2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。 29题 1.memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型。 2.redis 的速度比 memcached 快很多。 3.redis 可以持久化其数据。 4.Redis支持数据的备份,即master-slave模式的数据备份。 5.Redis采用VM机制。 6.value大小:redis最大可以达到1GB,而memcache只有1MB。 28题 Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过spring提供的@ImportResource来加载xml配置。例如:@ImportResource({"classpath:some-context.xml","classpath:another-context.xml"}) 27题 Spring像一个大家族,有众多衍生产品例如Spring Boot,Spring Security等等,但他们的基础都是Spring的IOC和AOP,IOC提供了依赖注入的容器,而AOP解决了面向切面的编程,然后在此两者的基础上实现了其他衍生产品的高级功能。Spring MVC是基于Servlet的一个MVC框架,主要解决WEB开发的问题,因为 Spring的配置非常复杂,各种xml,properties处理起来比较繁琐。Spring Boot遵循约定优于配置,极大降低了Spring使用门槛,又有着Spring原本灵活强大的功能。总结:Spring MVC和Spring Boot都属于Spring,Spring MVC是基于Spring的一个MVC框架,而Spring Boot是基于Spring的一套快速开发整合包。 26题 YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。YAML 的配置文件后缀为 .yml,是一种人类可读的数据序列化语言,可以简单表达清单、散列表,标量等数据形态。它通常用于配置文件,与属性文件相比,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。 25题 Spring Boot有3种热部署方式: 1.使用springloaded配置pom.xml文件,使用mvn spring-boot:run启动。 2.使用springloaded本地加载启动,配置jvm参数-javaagent:<jar包地址> -noverify。 3.使用devtools工具包,操作简单,但是每次需要重新部署。 用

游客ih62co2qqq5ww 2020-03-27 23:56:48 0 浏览量 回答数 0

问题

LM计算引擎 SELECT语法是什么?

nicenelly 2019-12-01 21:25:16 961 浏览量 回答数 0

问题

LM计算引擎 SELECT语法是什么?

nicenelly 2019-12-01 21:10:46 1307 浏览量 回答数 0

问题

短信接口调用错误码

nicenelly 2019-12-01 20:59:28 3100 浏览量 回答数 1

问题

如何在MySQL数据库中维护递归不变式?

保持可爱mmm 2019-12-01 21:58:03 4 浏览量 回答数 1

回答

*1、查询SQL尽量不要使用select ,而是select具体字段。 反例子: select * from employee; 正例子: select id,name from employee; 理由: 只取需要的字段,节省资源、减少网络开销。select * 进行查询时,很可能就不会使用到覆盖索引了,就会造成回表查询。 2、如果知道查询结果只有一条或者只要最大/最小一条记录,建议用limit 1 假设现在有employee员工表,要找出一个名字叫jay的人. CREATE TABLE `employee` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, `date` datetime DEFAULT NULL, `sex` int(1) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 反例: select id,name from employee where name='jay' 正例 select id,name from employee where name='jay' limit 1; 理由: 加上limit 1后,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。当然,如果name是唯一索引的话,是不必要加上limit 1了,因为limit的存在主要就是为了防止全表扫描,从而提高性能,如果一个语句本身可以预知不用全表扫描,有没有limit ,性能的差别并不大。 3、应尽量避免在where子句中使用or来连接条件 新建一个user表,它有一个普通索引userId,表结构如下: CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` int(11) NOT NULL, `age` int(11) NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), KEY `idx_userId` (`userId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 假设现在需要查询userid为1或者年龄为18岁的用户,很容易有以下sql 反例: select * from user where userid=1 or age =18 正例: //使用union all select * from user where userid=1 union all select * from user where age = 18 //或者分开两条sql写: select * from user where userid=1 select * from user where age = 18 理由: 使用or可能会使索引失效,从而全表扫描。 对于or+没有索引的age这种情况,假设它走了userId的索引,但是走到age查询条件时,它还得全表扫描,也就是需要三步过程: 全表扫描+索引扫描+合并 如果它一开始就走全表扫描,直接一遍扫描就完事。 mysql是有优化器的,处于效率与成本考虑,遇到or条件,索引可能失效,看起来也合情合理。 4、优化limit分页 我们日常做分页需求时,一般会用 limit 实现,但是当偏移量特别大的时候,查询效率就变得低下。 反例: select id,name,age from employee limit 10000,10 正例: //方案一 :返回上次查询的最大记录(偏移量) select id,name from employee where id>10000 limit 10. //方案二:order by + 索引 select id,name from employee order by id limit 10000,10 //方案三:在业务允许的情况下限制页数: 理由: 当偏移量最大的时候,查询效率就会越低,因为Mysql并非是跳过偏移量直接去取后面的数据,而是先把偏移量+要取的条数,然后再把前面偏移量这一段的数据抛弃掉再返回的。 如果使用优化方案一,返回上次最大查询记录(偏移量),这样可以跳过偏移量,效率提升不少。 方案二使用order by+索引,也是可以提高查询效率的。 方案三的话,建议跟业务讨论,有没有必要查这么后的分页啦。因为绝大多数用户都不会往后翻太多页。 5、优化你的like语句 日常开发中,如果用到模糊关键字查询,很容易想到like,但是like很可能让你的索引失效。 反例: select userId,name from user where userId like '%123'; 正例: select userId,name from user where userId like '123%'; 理由: 把%放前面,并不走索引,如下: 把% 放关键字后面,还是会走索引的。如下: 6、使用where条件限定要查询的数据,避免返回多余的行 假设业务场景是这样:查询某个用户是否是会员。曾经看过老的实现代码是这样。。。 反例: List<Long> userIds = sqlMap.queryList("select userId from user where isVip=1"); boolean isVip = userIds.contains(userId); 正例: Long userId = sqlMap.queryObject("select userId from user where userId='userId' and isVip='1' ") boolean isVip = userId!=null; 理由: 需要什么数据,就去查什么数据,避免返回不必要的数据,节省开销。 7、尽量避免在索引列上使用mysql的内置函数 业务需求:查询最近七天内登陆过的用户(假设loginTime加了索引) 反例: select userId,loginTime from loginuser where Date_ADD(loginTime,Interval 7 DAY) >=now(); 正例: explain select userId,loginTime from loginuser where loginTime >= Date_ADD(NOW(),INTERVAL - 7 DAY); 理由: 索引列上使用mysql的内置函数,索引失效 8、应尽量避免在 where 子句中对字段进行表达式操作,这将导致系统放弃使用索引而进行全表扫 反例: select * from user where age-1 =10; 正例: select * from user where age =11; 理由: 9、Inner join 、left join、right join,优先使用Inner join,如果是left join,左边表结果尽量小 Inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集 left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。 right join 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。 都满足SQL需求的前提下,推荐优先使用Inner join(内连接),如果要使用left join,左边表数据结果尽量小,如果有条件的尽量放到左边处理。 反例: select * from tab1 t1 left join tab2 t2 on t1.size = t2.size where t1.id>2; 正例: select * from (select * from tab1 where id >2) t1 left join tab2 t2 on t1.size = t2.size; 理由: 如果inner join是等值连接,或许返回的行数比较少,所以性能相对会好一点。 同理,使用了左连接,左边表数据结果尽量小,条件尽量放到左边处理,意味着返回的行数可能比较少。 10、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。 反例: select age,name from user where age <>18; 正例: //可以考虑分开两条sql写 select age,name from user where age <18; select age,name from user where age >18; 理由: 使用!=和<>很可能会让索引失效 11、使用联合索引时,注意索引列的顺序,一般遵循最左匹配原则。 表结构:(有一个联合索引idx_userid_age,userId在前,age在后) CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` int(11) NOT NULL, `age` int(11) DEFAULT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), KEY `idx_userid_age` (`userId`,`age`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 反例: select * from user where age = 10; 正例: //符合最左匹配原则 select * from user where userid=10 and age =10; //符合最左匹配原则 select * from user where userid =10; 理由: 当我们创建一个联合索引的时候,如(k1,k2,k3),相当于创建了(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则。 联合索引不满足最左原则,索引一般会失效,但是这个还跟Mysql优化器有关的。 12、对查询进行优化,应考虑在 where 及 order by 涉及的列上建立索引,尽量避免全表扫描。 反例: select * from user where address ='深圳' order by age ; 正例: 添加索引 alter table user add index idx_address_age (address,age) 13、如果插入数据过多,考虑批量插入。 反例: for(User u :list){ INSERT into user(name,age) values(#name#,#age#) } 正例: //一次500批量插入,分批进行 insert into user(name,age) values <foreach collection="list" item="item" index="index" separator=","> (#{item.name},#{item.age}) </foreach> 理由: 批量插入性能好,更加省时间 打个比喻:假如你需要搬一万块砖到楼顶,你有一个电梯,电梯一次可以放适量的砖(最多放500),你可以选择一次运送一块砖,也可以一次运送500,你觉得哪个时间消耗大? 14、在适当的时候,使用覆盖索引。 覆盖索引能够使得你的SQL语句不需要回表,仅仅访问索引就能够得到所有需要的数据,大大提高了查询效率。 反例: // like模糊查询,不走索引了 select * from user where userid like '%123%' 正例: //id为主键,那么为普通索引,即覆盖索引登场了。 select id,name from user where userid like '%123%'; 15、慎用distinct关键字 distinct 关键字一般用来过滤重复记录,以返回不重复的记录。在查询一个字段或者很少字段的情况下使用时,给查询带来优化效果。但是在字段很多的时候使用,却会大大降低查询效率。 反例: SELECT DISTINCT * from user; 正例: select DISTINCT name from user; 理由: 带distinct的语句cpu时间和占用时间都高于不带distinct的语句。因为当查询很多字段时,如果使用distinct,数据库引擎就会对数据进行比较,过滤掉重复数据,然而这个比较,过滤的过程会占用系统资源,cpu时间。 16、删除冗余和重复索引 反例: KEY `idx_userId` (`userId`) KEY `idx_userId_age` (`userId`,`age`) 正例: //删除userId索引,因为组合索引(A,B)相当于创建了(A)和(A,B)索引 KEY `idx_userId_age` (`userId`,`age`) 理由: 重复的索引需要维护,并且优化器在优化查询的时候也需要逐个地进行考虑,这会影响性能的。 17、如果数据量较大,优化你的修改/删除语句。 避免同时修改或删除过多数据,因为会造成cpu利用率过高,从而影响别人对数据库的访问。 反例: //一次删除10万或者100万+? delete from user where id <100000; //或者采用单一循环操作,效率低,时间漫长 for(User user:list){ delete from user; } 正例: //分批进行删除,如每次500 delete user where id<500 delete product where id>=500 and id<1000; 理由: 一次性删除太多数据,可能会有lock wait timeout exceed的错误,所以建议分批操作。 18、where子句中考虑使用默认值代替null。 反例: select * from user where age is not null; 正例: //设置0为默认值 select * from user where age>0; 理由: 并不是说使用了is null 或者 is not null 就会不走索引了,这个跟mysql版本以及查询成本都有关。 如果mysql优化器发现,走索引比不走索引成本还要高,肯定会放弃索引,这些条件!=,>is null,is not null经常被认为让索引失效,其实是因为一般情况下,查询的成本高,优化器自动放弃的。 如果把null值,换成默认值,很多时候让走索引成为可能,同时,表达意思会相对清晰一点。 19、不要有超过5个以上的表连接 连表越多,编译的时间和开销也就越大。 把连接表拆开成较小的几个执行,可读性更高。 如果一定需要连接很多表才能得到数据,那么意味着糟糕的设计了。 20、exist & in的合理利用 假设表A表示某企业的员工表,表B表示部门表,查询所有部门的所有员工,很容易有以下SQL: select * from A where deptId in (select deptId from B); 这样写等价于: 先查询部门表B select deptId from B 再由部门deptId,查询A的员工 select * from A where A.deptId = B.deptId 可以抽象成这样的一个循环: List<> resultSet ; for(int i=0;i<B.length;i++) { for(int j=0;j<A.length;j++) { if(A[i].id==B[j].id) { resultSet.add(A[i]); break; } } } 显然,除了使用in,我们也可以用exists实现一样的查询功能,如下: select * from A where exists (select 1 from B where A.deptId = B.deptId); 因为exists查询的理解就是,先执行主查询,获得数据后,再放到子查询中做条件验证,根据验证结果(true或者false),来决定主查询的数据结果是否得意保留。 那么,这样写就等价于: select * from A,先从A表做循环 select * from B where A.deptId = B.deptId,再从B表做循环. 同理,可以抽象成这样一个循环: List<> resultSet ; for(int i=0;i<A.length;i++) { for(int j=0;j<B.length;j++) { if(A[i].deptId==B[j].deptId) { resultSet.add(A[i]); break; } } } 数据库最费劲的就是跟程序链接释放。假设链接了两次,每次做上百万次的数据集查询,查完就走,这样就只做了两次;相反建立了上百万次链接,申请链接释放反复重复,这样系统就受不了了。即mysql优化原则,就是小表驱动大表,小的数据集驱动大的数据集,从而让性能更优。 因此,我们要选择最外层循环小的,也就是,如果B的数据量小于A,适合使用in,如果B的数据量大于A,即适合选择exist。 21、尽量用 union all 替换 union 如果检索结果中不会有重复的记录,推荐union all 替换 union。 反例: select * from user where userid=1 union select * from user where age = 10 正例: select * from user where userid=1 union all select * from user where age = 10 理由: 如果使用union,不管检索结果有没有重复,都会尝试进行合并,然后在输出最终结果前进行排序。如果已知检索结果没有重复记录,使用union all 代替union,这样会提高效率。 22、索引不宜太多,一般5个以内。 索引并不是越多越好,索引虽然提高了查询的效率,但是也降低了插入和更新的效率。 insert或update时有可能会重建索引,所以建索引需要慎重考虑,视具体情况来定。 一个表的索引数最好不要超过5个,若太多需要考虑一些索引是否没有存在的必要。 23、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型 反例: king_id` varchar(20) NOT NULL COMMENT '守护者Id' 正例: `king_id` int(11) NOT NULL COMMENT '守护者Id'` 理由: 相对于数字型字段,字符型会降低查询和连接的性能,并会增加存储开销。 24、索引不适合建在有大量重复数据的字段上,如性别这类型数据库字段。 因为SQL优化器是根据表中数据量来进行查询优化的,如果索引列有大量重复数据,Mysql查询优化器推算发现不走索引的成本更低,很可能就放弃索引了。 25、尽量避免向客户端返回过多数据量。 假设业务需求是,用户请求查看自己最近一年观看过的直播数据。 反例: //一次性查询所有数据回来 select * from LivingInfo where watchId =useId and watchTime >= Date_sub(now(),Interval 1 Y) 正例: //分页查询 select * from LivingInfo where watchId =useId and watchTime>= Date_sub(now(),Interval 1 Y) limit offset,pageSize //如果是前端分页,可以先查询前两百条记录,因为一般用户应该也不会往下翻太多页, select * from LivingInfo where watchId =useId and watchTime>= Date_sub(now(),Interval 1 Y) limit 200 ; 26、当在SQL语句中连接多个表时,请使用表的别名,并把别名前缀于每一列上,这样语义更加清晰。 反例: select * from A inner join B on A.deptId = B.deptId; 正例: select memeber.name,deptment.deptName from A member inner join B deptment on member.deptId = deptment.deptId; 27、尽可能使用varchar/nvarchar 代替 char/nchar。 反例: `deptName` char(100) DEFAULT NULL COMMENT '部门名称' 正例: `deptName` varchar(100) DEFAULT NULL COMMENT '部门名称' 理由: 因为首先变长字段存储空间小,可以节省存储空间。 其次对于查询来说,在一个相对较小的字段内搜索,效率更高。 28、为了提高group by 语句的效率,可以在执行到该语句前,把不需要的记录过滤掉。 反例: select job,avg(salary) from employee group by job having job ='president' or job = 'managent' 正例: select job,avg(salary) from employee where job ='president' or job = 'managent' group by job; 29、如何字段类型是字符串,where时一定用引号括起来,否则索引失效 反例: select * from user where userid =123; 正例: select * from user where userid ='123'; 理由: 为什么第一条语句未加单引号就不走索引了呢? 这是因为不加单引号时,是字符串跟数字的比较,它们类型不匹配,MySQL会做隐式的类型转换,把它们转换为浮点数再做比较。 30、使用explain 分析你SQL的计划 日常开发写SQL的时候,尽量养成一个习惯吧。用explain分析一下你写的SQL,尤其是走不走索引这一块。 explain select * from user where userid =10086 or age =18;

剑曼红尘 2020-04-21 14:01:32 0 浏览量 回答数 0

回答

OK OK 表示接口调用成功。 isv.SMS_SIGNATURE_SCENE_ILLEGAL 短信所使用签名场景非法 原因:签名的适用场景与短信类型不匹配。 解决方案:请选择合适的签名和模版进行短信发送。 适用场景为验证码的签名可与验证码模版匹配发送。 适用场景为通用的签名可与验证码、短信通知、推广短信、国际/港澳台短信模版匹配发送。 isv.EXTEND_CODE_ERROR 扩展码使用错误,相同的扩展码不可用于多个签名 原因:发送短信时不同签名的短信使用了相同扩展码。 解决方案:在调用短信发送接口时,不同的短信签名使用不同的扩展码。 isv.DOMESTIC_NUMBER_NOT_SUPPORTED 国际/港澳台消息模板不支持发送境内号码 原因:国际/港澳台消息模板仅支持发送国际、港澳台地区的号码。 解决方案:如果想发送境内短信,请申请国内短信模版。 isv.DENY_IP_RANGE 源IP地址所在的地区被禁用 原因:被系统检测到源IP属于非中国大陆地区。 解决方案:请将源IP地址修改为中国大陆地区的IP地址。港澳台、及海外地区的IP地址禁止发送国内短信业务。 isv.DAY_LIMIT_CONTROL 触发日发送限额 原因:已经达到您在控制台设置的短信日发送量限额值。 解决方案:如需修改限额,请在短信服务控制台左侧导航栏中单击国内消息设置 > 安全设置,修改发送总量阈值。 isv.SMS_CONTENT_ILLEGAL 短信内容包含禁止发送内容 原因:短信内容包含禁止发送内容。 解决方案:修改短信文案。 isv.SMS_SIGN_ILLEGAL 签名禁止使用 原因:签名禁止使用。 解决方案:请在短信服务控制台中申请符合规定的签名。 isp.RAM_PERMISSION_DENY RAM权限DENY 原因:RAM权限不足。 解决方案:请为当前使用的AK对应子账号进行授权:AliyunDysmsFullAccess(管理权限)。具体操作请参考:访问权限控制。 isv.OUT_OF_SERVICE 业务停机 原因:余额不足。余额不足时,套餐包中即使有短信额度也无法发送短信。 解决方案:请及时充值。 如果余额大于零仍报此错误,请通过工单联系工程师处理。 isv.PRODUCT_UN_SUBSCRIPT 未开通云通信产品的阿里云客户 原因: 该AK所属的账号尚未开通云通信的服务,包括短信、语音、流量等服务。 解决方案:当出现此类提示报错需要检查当前AK是否已经开通阿里云云通信短信服务,如已开通消息服务,则参照消息服务文档调用接口。 isv.PRODUCT_UNSUBSCRIBE 产品未开通 原因: 该AK所属的账号尚未开通当前接口的产品,例如仅开通了短信服务的用户调用语音接口时会产生此报错信息。 解决方案:检查AK对应账号是否已开通调用接口对应的服务。开通短信服务请单击短信服务产品介绍。 isv.ACCOUNT_NOT_EXISTS 账户不存在 原因: 使用了错误的账户名称或AK。 解决方案:请确认账号信息。 isv.ACCOUNT_ABNORMAL 账户异常 原因:账户异常。 解决方案: 请确认账号信息。 isv.SMS_TEMPLATE_ILLEGAL 短信模版不合法 原因: 短信模板不存在,或未经审核通过。 解决方案: 参数TemplateCode请传入审核通过的模版ID,模版ID请在控制台模板管理页面中查看。 isv.SMS_SIGNATURE_ILLEGAL 短信签名不合法 原因: 签名不存在,或未经审核通过。 解决方案:参数SignName请传入审核通过的签名名称,签名请在控制台签名管理页面中查看。 isv.INVALID_PARAMETERS 参数异常 原因: 参数格式不正确。 解决方案:请根据对应的API文档检查参数格式。 例如,短信查询接口QuerySendDetails的参数SendDate日期格式为yyyyMMdd,正确格式为20170101,错误格式为2017-01-01。 isp.SYSTEM_ERROR isp.SYSTEM_ERROR 原因: 系统错误。 解决方案:请重新调用接口,如仍存在此情况请创建工单反馈工程师查看。 isv.MOBILE_NUMBER_ILLEGAL 非法手机号 原因:手机号码格式错误。 解决方案:参数PhoneNumbers请传入正确的格式。 国内短信:11位手机号码,例如15951955195。 国际/港澳台消息:国际区号+号码,例如85200000000。 isv.MOBILE_COUNT_OVER_LIMIT 手机号码数量超过限制 原因:参数PhoneNumbers中指定的手机号码数量超出限制。 解决方案:请将手机号码数量限制在1000个以内。 isv.TEMPLATE_MISSING_PARAMETERS 模版缺少变量 原因: 参数TemplateParam中,变量未全部赋值。 解决方案: 请JSON格式字符串为模板变量赋值。 例如,模版为您好${name},验证码${code},则参数TemplateParam可以指定为{"name":"Tom","code":"123"}。 isv.BUSINESS_LIMIT_CONTROL 业务限流 原因: 短信发送频率超限。 解决方案: 请将短信发送频率限制在正常的业务流控范围内。默认流控:使用同一个签名,对同一个手机号码发送短信验证码,支持1条/分钟,5条/小时 ,累计10条/天。 isv.INVALID_JSON_PARAM JSON参数不合法,只接受字符串值 原因:参数格式错误,不是合法的JSON格式。 解决方案: 请在参数TemplateParam中指定正确的JSON格式字符串,例如{"code":"123"}。 isv.BLACK_KEY_CONTROL_LIMIT 黑名单管控 原因: 黑名单管控是指变量内容含有限制发送的内容,例如变量中不允许透传URL。 解决方案: 请检查通过变量是否透传了一些敏感信息。 isv.PARAM_LENGTH_LIMIT 参数超出长度限制 原因:参数超出长度限制。 解决方案:每个变量的长度限制为1~20字符。请修改参数长度。 isv.PARAM_NOT_SUPPORT_URL 不支持URL 原因: 黑名单管控是指变量内容含有限制发送的内容,例如变量中不允许透传URL。 解决方案: 请检查通过变量是否透传了URL或敏感信息。 isv.AMOUNT_NOT_ENOUGH 账户余额不足 原因: 当前账户余额不足。 解决方案:请及时充值。调用接口前请确认当前账户余额是否足以支付预计发送的短信量。 isv.TEMPLATE_PARAMS_ILLEGAL 模版变量里包含非法关键字 原因:变量内容含有限制发送的内容,例如变量中不允许透传URL。 解决方案: 请检查通过变量是否透传了URL或敏感信息。 SignatureDoesNotMatch Specified signature is not matched with our calculation. 原因: 签名(Signature)加密错误。 解决方案: 如果使用SDK调用接口,请注意accessKeyId和accessKeySecret字符串赋值正确。 如果自行加密签名(Signature),请对照文档检查加密逻辑。 InvalidTimeStamp.Expired Specified time stamp or date value is expired. 原因: 一般由于时区差异造成时间戳错误,发出请求的时间和服务器接收到请求的时间不在15分钟内。 阿里云网关使用的时间是GMT时间。 解决方案:请使用GMT时间。 SignatureNonceUsed Specified signature nonce was used already. 原因: 唯一随机数重复,SignatureNonce为唯一随机数,用于防止网络重放攻击。 解决方案: 不同请求请使用不同的随机数值。 InvalidVersion Specified parameter Version is not valid. 原因: 版本号(Version)错误。 解决方案:请确认接口的版本号,短信服务的API版本号(Version)为2017-05-25。 InvalidAction.NotFound Specified api is not found, please check your url and method 原因: 参数Action中指定的接口名错误。 解决方案: 请在参数Action中使用正确的接口地址和接口名。 isv.SIGN_COUNT_OVER_LIMIT 一个自然日中申请签名数量超过限制。 原因:一个自然日中申请签名数量超过限制。 解决方案:合理安排每天的签名申请数量,次日重新申请。 isv.TEMPLATE_COUNT_OVER_LIMIT 一个自然日中申请模板数量超过限制。 原因:一个自然日中申请模板数量超过限制。 解决方案:合理安排每天的模板申请数量,次日重新申请。 isv.SIGN_NAME_ILLEGAL 签名名称不符合规范。 原因:签名名称不符合规范。 解决方案:参考个人用户签名规范或企业用户签名规范重新申请签名。 isv.SIGN_FILE_LIMIT 签名认证材料附件大小超过限制。 原因:签名认证材料附件大小超过限制。 解决方案:压缩签名认证材料至2 MB以下。 isv.SIGN_OVER_LIMIT 签名字符数量超过限制。 原因:签名的名称或申请说明的字数超过限制。 解决方案:修改签名名称或申请说明,并重新提交审核。 isv.TEMPLATE_OVER_LIMIT 签名字符数量超过限制。 原因:模板的名称、内容或申请说明的字数超过限制。 解决方案:修改模板的名称、内容或申请说明,并重新提交审核。

保持可爱mmm 2020-03-27 10:02:47 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 云栖号物联网 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 云栖号弹性计算 阿里云云栖号 云栖号案例 云栖号直播