如何定义自动增量到端口字段

时间:2017-06-22 04:21:52

标签: sqlite

在我的脚本中,我想将端口字段列声明为自动增量,默认值为8080。

#!/bin/bash

echo " --- Enter the Database name ---"
read databasename


echo " --- enter the table name --- "
read table_name

sqlite3 $databasename.db "DROP TABLE IF EXISTS $table_name;"

sqlite3 $databasename.db  "CREATE TABLE IF NOT EXISTS $table_name(cus_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,cus_name TEXT NOT NULL UNIQUE ,cus_domain TEXT UNIQUE, cus_status TEXT NOT NULL,Port INTEGER NOT NULL);"


echo " --- Enter the total number of rows do you want ---"
read cus_count


echo "--- Enter the following details one by one---"

port_num=8080

for((i=1;i<=cus_count;i++))
do
port_number=$port_num

port_number=$((port_number + 1))

echo "port number is $port_number"

echo "enter the $i customer details"

echo "---Enter the customer name---"
read c_name

echo "---Enter the Status(Active/Inactive)---"
read c_status


c_domain="$c_name"

sqlite3 $databasename.db "INSERT OR IGNORE INTO $table_name (cus_name,cus_domain,cus_status, Port) VALUES(\"$c_name\",\"${c_domain,,}\",\"$c_status\",\"$port_number\") ;" 

done

echo " --- Records from the $table_name ---"

sqlite3 $databasename.db "select * from $table_name;"

如何定义自动增量到端口字段?

2 个答案:

答案 0 :(得分:0)

在SQLite中,autoincrementing仅适用于主键,端口号不是PK,也不应该是。

您必须使用自己的变量来增加端口号。 (你已经在做了什么。)

问题是您使用的是两个变量:

for((i=1;i<=cus_count;i++))
do
port_number=$port_num
port_number=$((port_number + 1))

您正在递增port_number,但在每次循环迭代中将其重置为旧值(port_num)。

你应该在循环之前只阅读port_num一次;或使用单个变量;或者将新值写回另一个变量。

答案 1 :(得分:0)

正如其他答案所阐述的那样,automincrement无法作为解决问题的工具。

你能做什么
(几乎完全是您的表模式,只是端口列的另一个UNIQUE) 是添加一个触发器和一个“harcoded”虚拟线 实现了什么(使用我在下面提出的触发器,但细节可以适应任何适用于数据库中端口使用的规则):

  • 输入有效(&gt; 8080)和未使用的端口号
    它被输入数据库
  • 输入无效(&lt; 8080)端口号
    它被最低的,有效的,未使用的,替换为
  • 之前,即使特定端口号选择导致间隙
  • 删除数据库条目,
    端口号将在以后重用
  • 输入已使用的端口号
    导致“独特的失败”(就像在您的设置中输入已经使用过的客户域一样)
  • 用于您的脚本,您可以跳过端口号的所有计算 而是
    • 允许输入端口号(数据库将防止双打)
    • 只需使用“1”作为portnumber(数据库将找到合适的数据库)

要记住一件事:
每当你读出列表时,你都需要以某种方式忽略虚拟线。

代码:

CREATE TRIGGER autoport AFTER INSERT ON cusports
BEGIN 
    UPDATE cusports
    SET port=
        (SELECT MIN(a.port+1)
         FROM  
                (SELECT * FROM cusports WHERE port >=8080)
                AS a
            LEFT JOIN
                cusports AS b
            ON a.port+1 = b.port
         WHERE b.port IS NULL)
    WHERE port<8080;
END;

INSERT INTO cusports(cus_id, cus_name, cus_domain, cus_status, Port)
VALUES(NULL,'dummycusname','dummycusdomain','dummycusstatus',8080);

详细说明:

  • 我正在草莓的答案上建立 Returning the lowest integer not in a list in SQL
  • (SELECT * FROM cusports WHERE port >=8080)而非简单cusports
    为了不使用可能无效的新插入端口ID
  • SELECT MIN(a.port+1)查找最小端口号“ 1比现有的更高,而不存在”( italic 中的部分是草莓的)
  • WHERE port<8080将更新限制为仅无效的端口号 (不想搞乱现有的条目)
  • 虚拟线用于草莓的方法,实际上没有找到所有不存在的数字,但只列出“比现有的高一个”

使用输出进行测试(SQLite命令行工具,在空表上设置触发器和虚拟线后):

sqlite> select * from cusports;
cus_id      cus_name      cus_domain      cus_status      Port
----------  ------------  --------------  --------------  ----------
1           dummycusname  dummycusdomain  dummycusstatus  8080 

sqlite> insert into cusports values (null, 'cusa', 'doma', 'stata', 8081);
sqlite> select * from cusports;
cus_id      cus_name      cus_domain      cus_status      Port
----------  ------------  --------------  --------------  ----------
1           dummycusname  dummycusdomain  dummycusstatus  8080
2           cusa          doma            stata           8081

sqlite> insert into cusports values (null, 'cusb', 'domb', 'statb', 8083);
sqlite> select * from cusports;
cus_id      cus_name      cus_domain      cus_status      Port
----------  ------------  --------------  --------------  ----------
1           dummycusname  dummycusdomain  dummycusstatus  8080
2           cusa          doma            stata           8081
3           cusb          domb            statb           8083
sqlite> -- note the 8082 gap and the following invalid '1'
sqlite> insert into cusports values (null, 'cusc', 'domc', 'statc', 1);
sqlite> select * from cusports;
cus_id      cus_name      cus_domain      cus_status      Port
----------  ------------  --------------  --------------  ----------
1           dummycusname  dummycusdomain  dummycusstatus  8080
2           cusa          doma            stata           8081
3           cusb          domb            statb           8083
4           cusc          domc            statc           8082
sqlite> insert into cusports values (null, 'cusd', 'domd', 'statd', 1);
sqlite> select * from cusports;
cus_id      cus_name      cus_domain      cus_status      Port
----------  ------------  --------------  --------------  ----------
1           dummycusname  dummycusdomain  dummycusstatus  8080
2           cusa          doma            stata           8081
3           cusb          domb            statb           8083
4           cusc          domc            statc           8082
5           cusd          domd            statd           8084
sqlite> delete from cusports where port=8083;
sqlite> select * from cusports;
cus_id      cus_name      cus_domain      cus_status      Port
----------  ------------  --------------  --------------  ----------
1           dummycusname  dummycusdomain  dummycusstatus  8080
2           cusa          doma            stata           8081
4           cusc          domc            statc           8082
5           cusd          domd            statd           8084
sqlite> insert into cusports values (null, 'cuse', 'dome', 'state', 1);
sqlite> select * from cusports;
cus_id      cus_name      cus_domain      cus_status      Port
----------  ------------  --------------  --------------  ----------
1           dummycusname  dummycusdomain  dummycusstatus  8080
2           cusa          doma            stata           8081
4           cusc          domc            statc           8082
5           cusd          domd            statd           8084
6           cuse          dome            state           8083

sqlite> insert into cusports values (null, 'cuse', 'dome', 'state', 1);
Error: UNIQUE constraint failed: cusports.cus_domain
sqlite> insert into cusports values(null, 'cusf', 'domf', 'statf', 8083);
Error: UNIQUE constraint failed: cusports.Port
sqlite> select * from cusports;
cus_id      cus_name      cus_domain      cus_status      Port
----------  ------------  --------------  --------------  ----------
1           dummycusname  dummycusdomain  dummycusstatus  8080
2           cusa          doma            stata           8081
4           cusc          domc            statc           8082
5           cusd          domd            statd           8084
6           cuse          dome            state           8083

完成.dump以供参考(一些希望更正新线以便于阅读):

PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE cusports(
    cus_id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
    cus_name TEXT NOT NULL UNIQUE,
    cus_domain TEXT UNIQUE,
    cus_status TEXT NOT NULL,
    Port INTEGER NOT NULL UNIQUE);
INSERT INTO cusports(cus_id,cus_name,cus_domain,cus_status,Port)
VALUES(1,'dummycusname','dummycusdomain','dummycusstatus',8080);
INSERT INTO cusports(cus_id,cus_name,cus_domain,cus_status,Port)
VALUES(2,'cusa','doma','stata',8081);
INSERT INTO cusports(cus_id,cus_name,cus_domain,cus_status,Port)
VALUES(4,'cusc','domc','statc',8082);
INSERT INTO cusports(cus_id,cus_name,cus_domain,cus_status,Port)
VALUES(5,'cusd','domd','statd',8084);
INSERT INTO cusports(cus_id,cus_name,cus_domain,cus_status,Port)
VALUES(6,'cuse','dome','state',8083);
DELETE FROM sqlite_sequence;
INSERT INTO sqlite_sequence(name,seq) VALUES('cusports',7);
CREATE TRIGGER autoport AFTER INSERT ON cusports
    BEGIN
        UPDATE cusports
        SET port=
            (SELECT MIN(a.port+1)
             FROM
                    (SELECT * FROM cusports WHERE port >=8080)
                    AS a
                LEFT JOIN
                    cusports AS b
                ON a.port+1 = b.port
             WHERE b.port IS NULL)
        WHERE port<8080;
    END;
COMMIT;