mysql中可以在表格没有输入任何数据的情况下设置字段为非空吗?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql中可以在表格没有输入任何数据的情况下设置字段为非空吗?相关的知识,希望对你有一定的参考价值。

不知道你为啥要这么问,没有数据当然可以这么设置了,如果有数据且设置列为空时,你设置非常,会提示设置不了,但没有数据的情况下,肯定是可以这么设置的。 参考技术A NULL 对外部程序来说,具体为不知道、不确切的、无法表述的值。所以在很多家公司的开发规范里都明确规定了,必须为 NOT NULL。
其实用到 NULL 的场景都可以转换为有意义的字符或者数值,一是有利用数据的易读性以及后期的易维护性;二是降低 SQL 语句的编写难度。
关于 NULL 的特性如下:
1. 参与 NULL 字段拼接的结果都为 NULL,预期的可能会有差异
预想把字段 r1 做个拼接,再插入到新的表 t3 里,结果 t3 表的记录全为 NULL,跟预期不符。
mysql> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`r1` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql> show create table t2\G
*************************** 1. row ***************************
Table: t2
Create Table: CREATE TABLE `t2` (
`r1` varchar(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql> create table t3 like t1
Query OK, 0 rows affected (0.04 sec)
mysql> insert into t3 select concat(r1,'database') from t1 limit 2;
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from t3;
+------+
| r1 |
+------+
| NULL |
| NULL |
+------+
2 rows in set (0.00 sec)
那正确的方法如下,对 NULL 用函数 IFNULL 特殊处理。
mysql> insert into t3 select concat(ifnull(r1,''),'database') from t1 limit 2;
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from t3;
+----------+
| r1 |
+----------+
| database |
| database |
+----------+
2 rows in set (0.00 sec)
2. 对于包含 NULL 列的求 COUNT 值也不准确
t1 和 t2 的记录数是一样的,但是字段 r1 包含了 NULL,这导致结果忽略了这些值。
mysql> select count(r1) as rc from t1;
+-------+
| rc |
+-------+
| 16384 |
+-------+
1 row in set (0.01 sec)
mysql> select count(r1) as rc from t2;
+-------+
| rc |
+-------+
| 32768 |
+-------+
1 row in set (0.03 sec)
这时候我们可能想到了,正确的方法是用 NULL 相关函数处理,
mysql> select count(ifnull(r1,'')) as rc from t1;
+-------+
| rc |
+-------+
| 32768 |
+-------+
1 row in set (0.03 sec)
或者是直接用 COUNT(*) 包含了所有可能的值
mysql> select count(*) as rc from t1;
+-------+
| rc |
+-------+
| 32768 |
+-------+
1 row in set (0.02 sec)
当然了不仅仅是 COUNT,除了 NULL 相关的函数,大部分对 NULL 处理都不友好。
所以其实从上面两点来看,NULL 的处理都得特殊处理,额外增加了编写 SQL 的难度。
3. 包含 NULL 的索引列
对包含 NULL 列建立索引,比不包含的 NULL 的字段,要多占用一个 BIT 位来存储。
示例
key_len 分别为 43 和 42,t1 比 t2 多了一个字节,那这里可能有人要问了,不是说占了一个 BIT 位吗?那为什么多了一个字节?可以关注我上一篇文章(第02期:MySQL 数据类型的艺术 - 大对象字段)关于 BIT 的详细描述。
mysql> pager grep -i 'key_len'
PAGER set to 'grep -i 'key_len''
mysql> explain select * from t1 where r1 = ''\G

key_len: 43
1 row in set, 1 warning (0.00 sec)
mysql> explain select * from t2 where r1 = ''\G

key_len: 42
1 row in set, 1 warning (0.00 sec)
4. 各存储引擎相关的对 NULL 的处理
在 MySQL 8.0 发布后,仅有 InnoDB、MyISAM 和 Memory 支持对包含 NULL 列的索引,其他引擎不支持。比如 NDB。

如何在没有验证码的情况下保护联系表格?

在我的网站上,我有几种形式,其中某人(没有注册)可以向指定的注册用户发送消息。形式很简单,我想保持这种方式。如果我不想使用任何验证码,保护联系表单的最佳方法是反击垃圾邮件和机器人?

Your message:...
Your e-mail:...
[Send]
答案

所以选项:

  1. 最大化查询/ IP
  2. 添加安全问题
  3. 验证码(即使你不喜欢它)
  4. 发送电子邮件以验证它
  5. 通过JavaScript提交数据

详细介绍了这些以及我对它们的看法。

  1. 它可以很好地防止发送许多消息,但它们的一些副本仍然可以进入。如果你认为这是可以承受的,这可能会有效。注意:垃圾邮件发送者可以使用代理或dinamic IP,但这可能会很慢。也许考虑不阻止用户,但如果他们发送太多电子邮件则添加验证码。
  2. 这究竟是什么?这些是诸如“10 + 1”或“10加1”或“它是哪一天?”之类的问题。他们可能会运作良好 - 如果您的网站只有很少的语言。 Captchas仍然更好,但这种情况很好。
  3. 你不喜欢它,但我仍然说它是最好的。添加一个reCAPTCHA并不是那么难,但它会阻止90%的垃圾邮件发送者 - 或更多。但是这有两个问题:1。有时候人类也无法阅读它.2。垃圾邮件发送者可以使用人来解决它的最低限度(例如0.001美元/验证码)数量,有时也可以。但这也代表案例2。
  4. 可能很好,但如果垃圾邮件发送者注意到这一点,他们可以生成随机电子邮件地址并通过SMTP验证它。但他们通常会去最容易的目标并离开。
  5. 好的,垃圾邮件发送者不能让机器人像点击一样,但他们可以制作代码,使点击不需要。但最简单的目标规则仍然存在。

在我看来,最好的是解决方案3,然后解决方案2,然后是解决方案1,然后是解决方案4和5。

另一答案

在我看来,许多网站(除卖票卖家,谷歌等主要网站以及其他将被定位的网站)可以通过组合使用多种不同的技术来阻止评论/形式垃圾邮件而无需验证码。我最近创建了一个开源PHP项目,它实现了以下测试,以确定提交是否合法或垃圾邮件。

  • 隐藏表单字段 - 如果填写了隐藏表单字段,则表示垃圾邮件
  • 时间表提交 - 如果表单填写过快或过慢,这是垃圾邮件的指示
  • 网址太多 - 如果评论字段包含太多网址(数字可配置),则表示垃圾邮件
  • 鼠标移动 - 如果用户不使用鼠标,则表示垃圾邮件
  • 二手键盘 - 如果用户不使用键盘,则表示垃圾邮件
  • 验证引用程序 - 如果HTTP引用程序与表单URL不匹配,我们不应接受提交。
  • 验证电子邮件 - 如果表单中提供的电子邮件地址从语法角度来看无效,我们不应接受提交。

这是项目的URL。我喜欢上面的Kaii测试,会为phpFormProtect做一个很好的额外测试。 https://github.com/mccarthy/phpFormProtect

另一答案

您可以使用表单键技术保护表单:

  1. 向用户显示表单时,只为此单个表单提交生成随机ID(“表单键”)。将表单键存储在会话变量中。在隐藏的输入字段中提交“表单键”。
  2. 在提交方面,检查提交的表单密钥与存储在会话变量中的密钥。使用后立即使其无效。 (从会话中删除)

如果没有验证码或类似的东西,就不可能真正保护表格免受滥用。

但是,使用这种技术的恶意垃圾邮件发送者必须这样做

  1. 通过HTTP为每个单一表单提交请求表单以获取有效的唯一forkey
  2. 解析DOM树/ HTML代码以获取表单密钥
  3. 以正确的格式提交

据我所知,没有自动垃圾邮件联系表单爬虫可以做到这一点。

此技术还可以保护您的表单免受多次提交的提交。

这是一个代码示例:

<?php
session_start();
if (isset($_POST['form_submit'])) {
  // do stuff
  if (isset($_POST['formkey']) && isset($_SESSION['formkeys'][$_POST['formkey']])) {
    echo "valid, doing stuff now ... "; flush();
    // delete formkey from session
    unset($_SESSION['formkeys'][$_POST['formkey']]);
    // release session early - after committing the session data is read-only
    session_write_close();
    // do whatever you like with the form data here
    send_contact_mail($_POST);
  }
  else {
    echo "request invalid or timed out.";
  }
}
else {
  // show form with formkey
  $formkey = md5("foo".microtime().rand(1,999999));
  // put current formkey into list of valid form keys for the user session
  if (!is_array($_SESSION['formkeys']) {
    $_SESSION['formkeys'] = array();
  ]
  $_SESSION['formkeys'][$formkey] = now();
?>
<html>
<head><title>form key</title></head>
<body>
  <form method="POST">
    <input type="hidden" name="PHPSESSID" value="<?=session_id()?>">
    <input type="text" name="formkey" 
      value="<?= $formkey ?>">
    <input type="submit" name="form_submit" value="Contact us!">
  </form>
</body>
</html>
<?php } ?>
另一答案

您可以从IP实施时间限制。因此,如果垃圾邮件机器人试图一次又一次地发送表单(在特定的时间间隔,比如1小时),则应该拒绝该请求。

您必须通过检查和存储用户的IP在服务器端执行此操作。然后,当他们再次发送表单时,检查用户是否已暂时处于被阻止的IP中。

这也是StackOverflow implemented 2年回来的原因。

另一答案

你可以做点什么来证明用户是人。如果你想保持简单,可能是一个问一个数学问题的字段,例如“2 + 5?”。但这不像验证码那么安全。但是,如果可能的垃圾邮件不会让你烦恼,那就可以了。

以上是关于mysql中可以在表格没有输入任何数据的情况下设置字段为非空吗?的主要内容,如果未能解决你的问题,请参考以下文章

我们如何在没有 MYSQL 负载的情况下创建 XML?

如何在没有任何排序参数的情况下从表格底部选择行......?

如何在没有验证码的情况下保护联系表格?

PHP & MySQL:检查表的数据是不是在没有轮询的情况下发生了变化?

有没有办法用 mysql_query 设置默认数据库句柄?

mysql自动增长主键怎么设置?