Mysql Data types in summary.

MySQL教程
本文详细介绍了MySQL中的数据定义语言(DDL)和数据操作语言(DML),包括创建、删除、修改数据库及表的相关命令,以及如何使用索引优化查询。此外,还深入探讨了MySQL支持的各种数据类型及其适用场景。
 
       MySQL commands (also referred to as statements) fall into two main categories:
       Data Definition Language (DDL)
       Data Manipulation Language (DML)
       The main Data Definition commands are CREATE, DROP, ALTER & RENAME
       The main Data Manipulation commands are SELECT, INSERT, UPDATE & DELETE
       MySQL data types fall into three main categories:
       string (character)
       Numeric
       date/time
       Each type has a number of subtypes, each with its own:
       storage requirements
       behavioural properties
 
 
CREATE DATABASE (Syntax)
CREATE DATABASE [IF NOT EXISTS] db_name;
CREATE DATABASE IF NOT EXISTS fortytwo; USE fortytwo;
       Creates a database with a given name.
       Database naming rules apply.
       [IF NOT EXISTS] optional but useful (don’t include parenthesis)
       Creates directory in MySQL data directory, but not tables.
DROP DATABASE
DROP DATABASE [IF EXISTS] db_name;
       Deletes a database including all resident tables.
       USE WITH GREAT CARE!
       [IF EXISTS] optional but useful (don’t include parenthesis)
CREATE TABLE
CREATE TABLE [IF NOT EXISTS] tbl_name [(create_definition,...)];
CREATE TABLE IF NOT EXISTS company (
 ABN                           INTEGER(8) UNSIGNED NOT NULL,
 company_name           VARCHAR(50), address        VARCHAR(100), phone         VARCHAR(10), PRIMARY KEY (ABN));
       Keep syntax neat and tidy by placing each column definition on a separate line, separated by a comma (,).
       All column names and definitions are contained within a single set of parenthesis ().
       Complete syntax with a semi-colon (;).
       Creates table with a given name within the database.
       Table naming rules apply
       [IF NOT EXISTS] optional but useful (don’t include parenthesis)
       A table cannot be created unless at least one column is also created within the table.
       Column naming rule:
       can be up to 64 characters long
       may contain alpha-numeric characters, an underscore (_) and a dollar sign ($).
       reserved words and complete numbers must not be used as column names unless enclosed in back-ticks (`).
       Each column name must be accompanied by a data type
       Attributes such as NOT NULL, ZEROFILL and UNSIGNED may also be assigned where applicable.
       A rule of order applies to column attributes, this being that type-specific attributes should always precede general attributes.
       For example, when a Numeric type is used, the UNSIGNED and ZEROFILL attributes must precede NULL or NOT NULL.
ALTER TABLE
ALTER [IGNORE] TABLE tbl_name alter_spec [, alter_spec ...];
       Changes the structure of an existing table.
       Add/delete columns, create/destroy indexes, change column types & rename columns.
       Alter specifications.
       [IGNORE] optional but useful (don’t include parenthesis)
RENAME TABLE
RENAME TABLE tbl_name TO new_tbl_name;
       Renames existing table.
       Can be used to rename multiple tables:
RENAME TABLE dog TO cat, up TO down, in TO out;
       Tables cannot be renamed to a name that is already in use.
DROP TABLE
DROP TABLE [IF EXISTS] tbl_name [, tbl_name,...] ;
DROP TABLE IF EXISTS company;
       Removes one or more tables.
       All table data is also deleted so USE WITH GREAT CARE!
       [IF EXISTS] optional but useful (don’t include parenthesis).
       Removes a table and all it’s objects from the MySQL data directory.
       CAREFUL!!! Unless transactional tables are being used in conjunction with the BEGIN and COMMIT commands, this action is permanent.
CREATE INDEX
CREATE [UNIQUE|FULLTEXT] INDEX index_name ON tbl_name (col_name[(length)],... );
       Allows the adding of indexes to a current table.
       Indexes can also be added to an existing table within the ALTER TABLE syntax.
       Indexes can also be created at the time of table creation within the CREATE TABLE syntax.
DROP INDEX
DROP INDEX index_name ON tbl_name;
       Drops a designated index from a table.
       Indexes can also be dropped from a table within the ALTER TABLE syntax.
 
 
SELECT
SELECT column_1 [,column_2,…] FROM tbl_name [WHERE condition];
SELECT * FROM workstation;
SELECT computerID, computerDescription FROM workstation WHERE computerDescription = ‘Apple Cube’;
SELECT computerID, computerDescription
FROM workstation
WHERE computerID <= 10;Displays the contents of every column for every tuple in the table indicated.
       Used to retrieve rows selected from one or more tables.
       FROM indicates the tables from which to retrieve rows.
       WHERE indicates conditions that rows must meet to be returned.
INSERT
INSERT INTO tbl_name (first_column,...last_column) VALUES (first_value,...last_value);
INSERT INTO company
            (ABN, company_name,address,phone)VALUES
            (10723485,'PIBT','24 Pearson St Churchlands', '0892758976');
       First the columns into which data is to be entered are named. The data values to be placed into these columns are then named in the SAME order.
       Literals are typed in without inverted commas (‘ ‘). Strings are typed in with inverted commas, eg. (‘PIBT’) for company_name.
            Aka
INSERT INTO company
VALUES
            (10723485,'PIBT','24 Pearson St Churchlands', '0892758976');
         In the event that all columns in a tuple are to receive data, and the data is stipulated in the same order that those columns appear in the table, stating the column names first is not necessary.
       Inserts new rows into an existing table.
       The columns into which the values are to be inserted are named first.
       VALUES indicates the data to be entered into the named columns.
       Rule of order applies.
       When using the full version of the INSERT statement,
INSERT INTO tbl_name (column1, column2…)
            VALUES (value1, value2…);
the values must appear in the same order as they appear in the column name declarations preceding them.
       When the shorthand version of the INSERT statement is being used, a value must be declared for every column in the table and in the same order as the columns appear in the table.
       Value data type must match the data type of the column into which it is being entered.
       In the event that values are only being entered into some, not all, of a tables columns, the omitted columns must either be set to NULL or to AUTO_INCREMENT if numeric.
       String and date values must be entered in single (‘) or double (“) quotes.
UPDATE
UPDATE tbl_name SET column_name = new_value [,next_column = new_value_2,...] WHERE column_name operator value [and|or column operator value];
UPDATE employee SET lastName = 'Skywalker' WHERE firstName = 'Darth';
In the table called ‘employee’, find the tuple that contains the string ‘Darth’ and in that same tuple, change the string in ‘lastName’ from whatever it currently is to ‘Skywalker’.
       Warning: UPDATE statements cannot be undone once executed so run a SELECT statement with the same WHERE clause first to make sure you know how many rows should be affected!!!
       Updates columns in existing table rows with new values.
       SET indicates the columns that will be affected by the change.
       WHERE indicates which rows will actually be changed in the fields indicated.
       Operators are usually mathematical in nature (=, >, < etc).
DELETE
DELETE FROM tbl_name [WHERE column_name operator value]
[and|or column operator value];
DELETE FROM employee WHERE lastName = 'Mouse';
       Deletes rows from table that satisfy the condition given by WHERE.
       DELETE with no WHERE clause results in all rows being deleted.
       Where tables reference one another via primary-foreign key relationships and InnoDB has not been applied to these tables, data anomalies are likely to result from data deletions.
 
 

       The string data type is designed to store a range of data objects other than those that are either numbers or dates.
       Although the string data type is most commonly used for its ability to store character data, its generality allows it to hold data objects that are not associated with any particular character set.
       Data objects that are not associated with any particular character set are known as binary strings. Binary strings are stored and processed on a byte-by-byte basis.
       Data objects that are associated with a character set (such as ASCII, EBCDIC, Unicode etc) are known as non-binary strings. These are stored and processed on a character-by-character basis.
 
       MySQL uses six (6) primary string types, these being CHAR, VARCHAR, BLOB, TEXT, ENUM and SET.
       The BLOB string type is comprised of four (4) specific types, these being the TINYBLOB, BLOB, MEDIUMBLOB and LONGBLOB.
       The TEXT string type is also comprised of four (4) specific types, these being TINYTEXT, TEXT, MEDIUMTEXT and LONGTEXT.
MySQL Column Types – Strings
         The string types are:
         CHAR
         VARCHAR
         BLOB
         TEXT
         ENUM
         SET
CHAR
       Commonly used string type.
       CHAR is a fixed-length string type, ie it takes up a fixed portion of memory, even if the size of the value entered is smaller.
       Values entered of a size less than a CHAR’s declared length (M) is stored with padding spaces to the right.
       The scale (M) declaration for CHAR is optional. If left out, it defaults to 1.
       Allowable size range is 1 to 255.
VARCHAR
       Another commonly used type of string.
       VARCHAR is a variable-length string type. As such, values entered into a column declared VARCHAR only occupy the amount of memory required to store them (M + 1 byte).
       When the value entered in a VARCHAR column is less than its declared maximum size, the trailing spaces are removed before storage in memory.
       The scale (M) declaration for VARCHAR is compulsory.
       Allowable size range is 1 to 255.
CHAR vs VARCHAR – Key Points
       Use CHAR when values entered into a column have little variance, especially if MyISAM or ISAM tables are being used. In this case, rows are processed more efficiently.
       Use VARCHAR when values entered into a column have significant variance, as this uses less memory space (an key processing-efficiency consideration).
       Do not mix CHAR and VARCHAR within the same table. In cases where this is done, MySQL usually alters the CHAR column to a VARCHAR without notification.
       Further, CHAR cannot be used in tables that also contain BLOB or TEXT columns, for these too are variable length string types.
CHAR, VARCHAR – Syntax
In this case, as the unit code is always an alph-numeric mix, seven characters in length (eg UI101), CHAR is the most appropriate string type to use. Note that no variable-length string types exist within the table.
CHAR
CREATE TABLE unit_det (
            unit_code CHAR(7),
            date_enrolled DATE);
As the length of student addresses will always vary greatly, VARCHAR is the most sensible string type to use. The difference between address length and declared max (100) will be stripped off at storage time.
VARCHAR
CREATE TABLE stud_det (
            stu_num INT(8),
            stu_add VARCHAR(100));
BLOB
       The BLOB type is designed to hold binary strings.
       These can include images, sounds and a range of other file types that are not associated with a particular character set.
       BLOB is versatile in that it can store data objects ranging from a very small size to a very large size.
(4Gbytes max in theory, 1Gbyte max in practice).
       BLOB takes four forms, which vary only in capacity.
       BLOB values are case sensitive.
BLOB – Type Capacities
       The BLOB faimily has four (4) members, these being:
       TINYBLOB
       BLOB
       MEDIUMBLOB
       LONGBLOB
 
 
TEXT
       The TEXT string type is very similar to BLOB, except that it is solely concerned with non-binary string data objects (those associated with specific character sets), along with specific operations that pertain to these.
       TINYTEXT
       TEXT
       MEDIUMTEXT
       LONGTEXT
 
       Their capacities are shown in the table below:
BLOB vs TEXT – Key Points
       Choose BLOB and TEXT types carefully, as the larger capacity types take up a great deal of memory space. Set columns to the specific type that will adequately cover the anticipated size of the objects to be placed into them, and no more.
       BLOB and TEXT columns can be used as indexes, but only in the following circumstances:
        The table concerned is of the MyISAM type. InnoDB and ISAM do not support indexing of these data types.
        A prefix size is specified. Indexes only work effectively if they are small in size (this facilitates rapid processing). As BLOB and TEXT fields can be extremely large, using them in their entirety negates a column’s value as an indexing instrument.
BLOB
In this case, students can upload a variety of files to a unit database. These objects can include images or sounds. The system is set up to accept files < 16Mbytes.
CREATE TABLE stud_contr (
            contr_num CHAR(7),
            contr MEDIUMBLOB);
In this case, the database is the back-end of a news article management system. Articles are always between 300 and 1,000 words in length and never exceed 64Kbytes in size.
TEXT
CREATE TABLE articles (
            art_num INT(5),
            article TEXT);
ENUM
       An ENUM (enumeration) is a string object whose contents is normally chosen from a list of allowed values that are enumerated (numbered, listed) explicitly in the column specification at table creation time.
       Only one legal value can occupy an ENUM column at any point in time. In other words, the selection must be mutually exclusive. A legal value is one chosen from the developer’s defined list of options.
       Values from the list of allowable elements in the column specification are numbered beginning with 1.
       An enumeration can have a maximum of 65,535 elements.
Example 1
A column that records if a loan applicant has taken out a loan with the bank on a previous occasion.
previous_loan ENUM(‘No’, ‘Yes’);
Example 2
A column records the color of product that a customer has elected.
product_colour ENUM(‘red’, ‘blue’, ‘green’);
 
SET
       A SET is a string object that will allow zero or more values to exist within it, each of which must be chosen from a list of allowed values specified when the table is created.
       Values in a SET are not mutually exclusive, ie more than one value can be selected.
       SET column values that consist of multiple set members are specified with members separated by commas (,). A consequence of this is that SET member values cannot themselves contain commas.
       A SET can have a maximum of 64 different members.
Example 1
A column that records the peripherals a customer would like to bundle with the purchase of a PC.
opt_ext_req SET(‘printer’, ‘scanner’, ‘modem’);
Example 2
A column that records those titles a customer would like to include in their bulk subscription.
titles_req SET(‘APC’, ‘PC Authority’, ‘Mac User’, ‘Computer World’, ‘IT Monthly’, ‘Linux World’);
 
       Numeric data types fall into two broad categories, these being integer values and floating-point values.
INTEGER: An integer is a numeric value that does not use a decimal point. In other words, it has no fractional component, eg 64, 127, 2116.
FLOATING-POINT: A floating-point value has both a whole and a fractional component, which are separated by a decimal point, eg 27.63, 0.2489, 26.0
Numeric
Exact:Numeric,Decimal,Integer
Approximate: Float,Real,Double Precision
The NUMERIC and DECIMAL types are implemented as the same type by MySQL, as permitted by the SQL92 standard. They are used for values for which it is important to preserve exact precision, for example with monetary data. When declaring a column of one of these types the precision and scale can be (and usually is) specified; for example:
salary DECIMAL(5,2)
       The whole component of a floating-point value is known as its precision, which is represented as M.
       The fractional component of a floating-point value is known as its scale, which is represented as D.
salary FLOAT(4,2); precision (M)        scale (D) 4 is precision 2 is scale
       A value of 1 to 255 can be stipulated for M.
       A value of 0 to 30 can be stipulated for D.
       Both of these value ranges refer to maximum display size, not the amount of memory required to store the value.
       To allow fine control over the way in which these broad numeric categories can be used and stored, they are divided into several specific types, each with their own unique properties. These are shown below:
Integer:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT
Floating-Point:FLOAT,DOUBLE,DECIMAL
 
Caution with Integers
       Oracle only has one Integral numeric type which is called “INTEGER”
       If you look at sql code and any of the columns have the type of “INTEGER”, then this code has been adapted from Oracle, and should be modified to use MySQL integral types
       Note that if you do not amend the column types then MySQL will parse the code, but will waste space by making all integral values use up 4 bytes, when a smaller integer type will often be sufficient
       Also note that inappropriate column types may cost you marks in the second assignment!
Numeric Data Types
TINYINT
       A very small number.
       Requires 1 byte (8 bits) of memory storage space.
       Can accommodate -128 to 127 when negative values need to be used (signed values).
       When negative values will not be used (unsigned values), TINYINT can accommodate values of 0 – 255.
SMALLINT
       A small number.
       Requires 2 bytes (16 bits) of memory storage space.
       -32768 to 32767 when signed.
       0 to 65535 unsigned.
MEDIUMINT
       A medium-sized number.
       Requires 3 bytes (24 bits) of memory storage space.
       -8388608 to 8388607 when signed.
       0 to 16777215 unsigned.
INT
       A standard number.
       Requires 4 bytes (32 bits) of memory storage space.
       -2147683648 to 2147683647 when signed.
       0 to 4294967295 unsigned.
BIGINT
       A large number.
       Requires 8 bytes (64 bits) of memory storage space.
       -263 to 263-1 when signed.
       0 to 264-1 unsigned.
FLOAT
       A single-precision floating-point number.
       Requires 4 bytes (32 bits) of memory storage space.
       Range expressed as minimum and maximum non-zero values.
       When expressed using scientific notation, equivalent to:
+/- 1.175494351E-38 (min) to +/- 3.402823466E+38 (max)
       Appropriate for most standard floating-point requirements.
DOUBLE
(aka DOUBLE PRECISION, REAL)(also know as real)
       A double-precision floating-point number.
       Requires 8 bytes (64 bits) of memory storage space.
       Range expressed as minimum and maximum non-zero values.
       When expressed using scientific notation, equivalent to:
+/- 2.2250738585072014E-308 (min) to
+/- 1.7976931348623157E+308 (max)
       Used for exceptionally high-precision requirements or extremely large ranges of values.
DECIMAL
(aka NUMERIC)
       A floating-point number represented as a string.
       Memory storage space required varies according to the precision (M) and scale (D) declared.
       Range also dictated by M and D declared.
       Example:- DECIMAL(4,1) allows range of:
            -999.9 to 9999.9 (minus sign included in M)
       DECIMAL is especially useful for currency calculations.
 
Numeric Data Types –Column Attributes
ZEROFILL
       Adds leading zeros to the unused display width of a column containing a numeric data type.
       Can be used with ALL numeric data types.
       Used to achieve display consistency within a column, i.e., ensures the same minimum number of digits in every tuple of a particular column.
       In the event that an entered value exceeds the ZEROFILL stipulation, the column display expands accordingly.
       Always fill in 0 to before value
mysql>CREATE TABLE stud_reg (
      =>stud_num INT(8) ZEROFILL);
mysql>INSERT INTO stud_reg VALUES 1;
mysql>INSERT INTO stud_reg VALUES 10;
mysql>INSERT INTO stud_reg VALUES 100;
mysql>INSERT INTO stud_reg VALUES 1000;
mysql>SELECT stud_num FROM stud_reg;
UNSIGNED
       Disallows negative values.
       Commonly applied to integer types.
       Should be used when entered values will never be negative, eg days a student attends a course throughout a year.
       If not used in this circumstance, leads to memory wastage and a reduced range of possible values that can be used. This is an important database design consideration.
UNSIGNED not used
CREATE TABLE stud_reg (
=>stud_num INT(8) ZEROFILL,
=>days_att TINYINT);
As TINYINT has not be specified as UNSIGNED, it is signed, ie has a negtaive component to its range as well as positive. This range is as follows:
-128 to 127
However, as this column will only ever have positive values entered into it, this negative range will take up memory space, yet never be used.
UNSIGNED used
CREATE TABLE stud_reg (
=>stud_num INT(8) ZEROFILL,
=>days_att TINYINT UNSIGNED);
As TINYINT has now been specified as UNSIGNED, it only has a positive component. Its range is now as follows:
0 to 255
The range of usable values has now effectively doubled and memory wastage has been avoided.
AUTO_INCREMENT
       Used to create unique identifier values serially.
       Can be stipulated for integer column types only.
       Generally commences at 1 and increments by 1.
       Automatically generates the next unique identifier in a series when a NULL value is entered into the column to which AUTO_INCREMENT is applied.
       AUTO_INCREMENT only applied to one column per table.
       Columns to which the AUTO_INCREMENT attribute is assigned should also:
       Be set to NOT NULL*
       Be declared a Primary Key or Unique Key
       Be declared UNSIGNED
Example
CREATE TABLE stud_reg (stud_num INT(8)UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY (stud_num));
 
* MySQL Version 3.23 and later automatically treat AUTO_INCREMENT columns as being NOT NULL.
 
 
       MySQL provides five (5) data types for temporal values.
       These are DATE, DATETIME, TIME, TIMESTAMP and YEAR.
       Each temporal data type has its own legal range of values and storage requirements.
       MySQL represents dates year first, eg 10 July, 2003 is represented in the database as 2003-07-10.
       Temporal data types are selected according to criteria such as storage efficiency, required precision of date-related calculations and the need for brevity.
Date/Time
       The date/time types are:
       DATETIME
       DATE
       TIMESTAMP
       TIME
       YEAR
Column type     Zero value
DATETIME     '0000-00-00 00:00:00'
DATE '0000-00-00'
TIMESTAMP 00000000000000 (length depends on display size)
TIME  '00:00:00'
YEAR 0000
 
DATE
       Legal range of values ‘1000-01-01’ to ‘9999-12-31’.
       Requires three (3) bytes of memory storage.
       Represented in alpha format as CCYY-MM-DD where CCYY (C=century, Y=year) represents the year, MM represents the month and DD represents the day.
       Zero value is ‘0000-00-00’.
       The zero value is inserted when an illegal entry is made, or when no value is entered but the NOT NULL attribute has been set.
TIME
       Legal range of values ‘-838:59:59’ to ‘838:59:59’.
       Requires three (3) bytes of memory storage.
       Represented in alpha format as hh:mm:ss where hh represents the hour, mm represents the minute and ss represents the second.
       Zero value is ’00:00:00’.
       Represents elapsed time rather than fixed time, thus explaining the large range of possible values.
DATETIME
       Legal range of values
            ‘1000-01-01 00:00:00’ to
            ‘9999-12-31 23:59:59’
       Requires eight (8) bytes of memory storage.
       Represented in alpha format as
            CCYY-MM-DD hh:mm:ss
       Zero value is ‘0000-00-00 00:00:00’.
TIMESTAMP
       Legal range of values ‘1970-01-01 00:00:00’ to an uncertain point in ‘2037’
       Requires four (4) bytes of memory storage.
       Zero value is ‘00000000000000’ for TIMESTAMP(14).
       TIMESTAMP(M) has seven specifications these being: TIMESTAMP(2|4|6|8|10|12|14).
       TIMESTAMP(2) is equivalent to YY.
       TIMESTAMP(14) is equivalent to CCYYMMDDhhmmss.
       TIMESTAMP defaults to (14) when M is not stated.
YEAR
       Legal range of values ‘1901 to 2155’ if YEAR(4) is stipulated, ‘1970 to 2069’ if YEAR(2) is stipulated.
       Requires one (1) byte of memory storage.
       Zero value is ‘0000’ for YEAR(4).
       YEAR(2) only displays last two digits, ie YY.
       YEAR(4) displays as four digits, ie CCYY.
       YEAR defaults to (4) when M is not stated.
Considerations When Selecting Column Data Types
       Determine the data type of the values a column will hold.
       If numeric, determine if negative values will be required. If not, use the UNSIGNED attribute.
       Determine how data type selection will impact upon processing performance. For example, if CHAR is used when values will vary in size considerably, memory wastage is likely to occur. Use VARCHAR instead.
       Determine if values will be subject to comparison. If string objects are to be compared for example, determine if this will be done on a case sensitive or non-case sensitive basis.
       Determine if a column is to be indexed. Not all data types make ideal indexes. For example, BLOB does not make an ideal index, but if used, needs to have special constraints applied to it.
       Generally speaking, always look for the long term consequences column data type selection will have upon the efficiency and stability of a database’s operation.
 Take Notes For  learning purposes
src/ ├── controller/ auto-publish/ │ └── index.ts ├── model/ # 数据模型目录 │ ├── publish-info/index.ts │ ├── publish-record/index.ts │ ├── associations.ts # 原有的关联模型 │ └── types/ # TypeScript 类型定义 │ └── autoPublish.ts ├── services/auto-publish/ # 服务层目录 │ └── index.ts ├── routes/ # 路由目录(由 TSOA 自动生成) ├── middleware/ # 中间件目录 ├── utils/ # 工具函数目录 ├── config/ # 配置文件目录 └── main.ts # Express 应用入口 基于以上的结构目录帮我重构一下接口,其中: //原有接口: import { publish_info, publish_record } from "../../model/associations"; import { Op, Transaction, where } from "sequelize"; import { Request, Response } from "express"; import { exec } from "child_process"; import fs from "fs"; import path from "path"; import yaml from "js-yaml"; import dayjs from "dayjs"; import sequelize from "../../mysql"; /** * @openapi * /configserver/getPublishRecordWithInfo: * get: * summary: 获取发布记录及关联的发布信息 * description: 根据分支版本查询发布记录并关联查询对应的发布信息 * parameters: * - in: query * name: branch_version * schema: * type: string * description: 分支版本 * - in: query * name: page * schema: * type: integer * description: 页码 * - in: query * name: pageSize * schema: * type: integer * description: 每页条数 * - in: query * name: publish_status * schema: * type: integer * description: 发布状态 * - in: query * name: publish_env * schema: * type: integer * description: 发布环境 * responses: * '200': * description: 成功获取发布记录及关联信息 * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * data: * type: object * properties: * record: * type: array * items: * $ref: '#/components/schemas/PublishRecord' * totalCount: * type: integer * description: 总记录数 * message: * type: string */ exports.getPublishRecordWithInfo = async (req: Request, res: Response) => { try { const { branch_version, page, pageSize, publish_status, publish_env } = req.query; if (!page || !pageSize) { res.status(400).send({ success: false, message: "缺少page或pageSize参数", }); return; } let search: { limit: number; offset: number; where?: { branch_version?: string; publish_status?: number; publish_env?: number; }; order: [string, "DESC" | "ASC"][]; } = { limit: +pageSize, offset: (+page - 1) * +pageSize, where: {}, order: [["publish_time", "DESC"]], }; if (branch_version && search.where) { search.where["branch_version"] = branch_version as string; } if (publish_status && search.where) { search.where["publish_status"] = Number(publish_status); } if (publish_env && search.where) { console.log(req.query); search.where["publish_env"] = Number(publish_env); } // const count = await publish_record.count(); // console.log(count); // 查询publish_record表中的记录 const record = await publish_record.findAll({ ...search, attributes: { exclude: ["createAt", "updateAt"] }, include: [ { model: publish_info, required: false, as: "products", // 将关联字段别名改为products以匹配模型定义 }, ], }); const count = await publish_record.count({ where: search.where, }); res.send({ success: true, data: record, totalCount: count, message: "查询成功", }); } catch (error) { console.error("查询发布记录及关联信息时出错:", error); res.status(500).send({ success: false, message: "查询失败", error: error instanceof Error ? error.message : String(error), }); } }; /** * @openapi * /configserver/delPublishRecordWithInfoById: * delete: * summary: 根据ID删除发布记录及关联的发布信息 * description: 根据ID删除发布记录,并级联删除关联的发布信息 * parameters: * - in: query * name: id * schema: * type: integer * required: true * description: 发布记录ID * responses: * '200': * description: 成功删除发布记录及关联信息 * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * message: * type: string */ exports.delPublishRecordWithInfoById = async (req: Request, res: Response) => { const { id } = req.query; try { const result = await sequelize.transaction(async (t: Transaction) => { const delInfo = await publish_info.destroy({ where: { publishRecordId: id }, }); // Then delete the publish_record const delRecord = await publish_record.destroy({ where: { id: id }, }); return { delInfo, delRecord }; }); // First delete associated publish_info records if (result.delRecord) { res.send({ success: true, message: "删除成功", }); } else { res.status(500).send({ success: false, message: "删除失败", data: result, }); } } catch (error) { console.error("删除发布记录及关联信息时出错:", error); res.status(500).send({ success: false, message: "删除失败", error: error instanceof Error ? error.message : String(error), }); } }; /** * 立即发布 */ type releaseType = { branch: string; tags: { LP_Annotation_Web: string; LP_Annotation_2D: string; LP_Annotation_3D: string; LP_Annotation_LaneMap: string; LP_Annotation_FileService: string; LP_Annotation_Management: string; LP_Annotation_Tookit: string; LP_Annotation_ConfigWeb: string; [x: string]: string; }; }; let timeInterval: { [x: string]: NodeJS.Timeout } = {}; let publishTimeout: { [x: string]: NodeJS.Timeout } = {}; const publishNow = ( res: Response, requestBody: Request["body"], branch_version: string ) => { console.log("branch_version:", branch_version); let publishyamlPath: string; if (requestBody.publish_env === 1) { publishyamlPath = "/test/annotation/deploy.yaml"; } else { publishyamlPath = "/prod/annotation/deploy.yaml"; } // fs.readFileSync(path.resolve(__dirname, "./release_tags.yaml")); fs.writeFileSync( path.resolve(__dirname, "../../../LP_VersionRelease" + publishyamlPath), yaml.dump({ version: requestBody.branch_version, description: `"标注子系统"`, }) ); const projectPath = path.resolve(__dirname, "../../../LP_VersionRelease"); const command = `cd "${projectPath}" && git pull && git add "**/**/deploy.yaml" && git commit -m "update annotation deploy.yaml ${branch_version}" && git push`; publishTimeout[branch_version] = setTimeout(() => { exec(command, (error, stdout, stderr) => { if (error) { console.error(`执行命令出错: ${error}`); return; } if (stderr) { console.error(`stderr: ${stderr}`); } console.log(`stdout: ${stdout} ${branch_version} 发布成功`); clearTimeout(publishTimeout[branch_version]); publish_record.update( { publish_status: 2 }, { where: { branch_version, }, } ); }); }, 10 * 1000); }; const changeReleaseTag = (res: Response, requestBody: Request["body"]) => { let releaseTags: releaseType = yaml.load( fs.readFileSync( path.resolve( __dirname, "../../../LP_Annotation_Version_Release/release_tags.yaml" ), "utf-8" ) ) as releaseType; let regExp = /V?\d+\.\d+\.\d+/; let branch_version: string = releaseTags.branch?.match(regExp)?.[0] as string; if (branch_version) { branch_version = branch_version?.slice(0, -1) + String(+branch_version?.slice(-1) + 1); } releaseTags.branch = (requestBody.branch_version || branch_version) + "[fu_wentao]"; requestBody.products.forEach((item: any) => { releaseTags.tags[item.product_name] = item.product_tag + (releaseTags.tags[item.product_name]?.match(/\[.*?\]/)?.[0] || "[fu_wentao]"); }); let versionText = yaml.dump(releaseTags); let lines = versionText.split("\n"); lines.splice(2, 0, `# ${requestBody.publish_env === 1 ? "test" : "prod"}`); versionText = lines.join("\n"); const releaseTagsPath = path.resolve( __dirname, "../../../LP_Annotation_Version_Release/release_tags.yaml" ); fs.writeFileSync(releaseTagsPath, versionText); const projectPath = path.resolve( __dirname, "../../../LP_Annotation_Version_Release" ); const command = `cd "${projectPath}" && git pull && git add "release_tags.yaml" && git commit -m "update release_tags.yaml" && git push`; exec(command, async (error, stdout, stderr) => { if (error) { console.error(`执行命令出错: ${error}`); res.status(500).send({ success: false, message: "Git命令执行失败", error: error.message, }); return; } if (stderr) { console.error(`stderr: ${stderr}`); // Not returning here as some git warnings might appear in stderr but command succeeds } console.log(`stdout: ${stdout}`); // Continue with the rest of the logic after successful git commit let publishList: { product_name: string; product_tag: string; branch_version: string; publishRecordId: number; }[] = []; try { const result = await sequelize.transaction(async (t: Transaction) => { const record = await publish_record.create( { branch_version: requestBody.branch_version, publish_time: requestBody.publish_time, publish_user: requestBody.publish_user, publish_status: 1, publish_type: requestBody.publish_type, publish_env: requestBody.publish_env, }, { transaction: t, } ); requestBody.products.forEach( (product: { product_name: string; product_tag: string }) => { publishList.push({ product_name: product.product_name, product_tag: product.product_tag, branch_version: requestBody.branch_version, publishRecordId: record.id, // 设置外键关联 }); } ); await publish_info.bulkCreate(publishList, { transaction: t }); return record; }); console.log(`${requestBody.branch_version}准备发布`); timeInterval[requestBody.branch_version] = setInterval(() => { let date = new Date(); if ( dayjs(date).format("YYYY-MM-DD HH:mm") == requestBody.publish_time.slice(0, -3) ) { console.log(`${requestBody.branch_version}开始发布`); clearInterval(timeInterval[requestBody.branch_version]); publishNow(res, requestBody, requestBody.branch_version); } }, 1000); // 确保返回创建的记录,包括其ID res.send({ success: true, data: result, message: "", }); } catch (error) { console.error("Error creating publish history:", error); res.status(500).send({ success: false, message: "创建失败", error: error instanceof Error ? error.message : String(error), }); } }); }; /** * @openapi * /configserver/setPublish: * post: * summary: 设置发布历史 * description: 该接口用于设置和记录产品发布历史信息 * parameters: * - in: query * name: publish_status * schema: * type: integer * description: 发布状态 1 待发布 2发布成功 3 发布失败 * - in: query * name: publish_type * schema: * type: integer * description: 发布类型 1 立即发布 2 预约发布 * - in: query * name: publish_env * schema: * type: string * description: 发布环境 1 测试环境 2 生产环境 * requestBody: * description: 包含产品发布信息的请求体 * required: true * content: * application/json: * schema: * type: object * description: 发布信息对象,包含产品列表和发布相关参数 * required: * - product * - branch_version * - publish_time * - publish_user * - publish_status * - publish_type * - publish_env * properties: * product: * type: array * description: 需要发布的產品列表 * items: * type: object * description: 單個產品的發布信息 * properties: * product_name: * type: string * example: "Lp_Annotation_Web" * description: 产品名称 * product_tag: * type: string * example: "v1.0.0" * description: 产品标签 * branch_version: * type: string * example: "1.0.0" * description: 分支版本 * publish_time: * type: string * example: "2023-07-07 12:00:00" * description: 发布时间 * publish_user: * type: string * example: "admin" * description: 发布人 * publish_status: * type: integer * description: 发布状态 1 待发布 2发布成功 3 发布失败 * publish_type: * type: integer * description: 发布类型 1 立即发布 2 预约发布 * publish_env: * type: integer * description: 发布环境 1 测试环境 2 生产环境 * responses: * '200': * description: 成功设置发布历史 * content: * application/json: * schema: * type: object * properties: * success: * type: boolean * description: 请求是否成功 * data: * type: array * description: 发布历史数据列表 * items: * type: object * properties: * product_name: * type: string * description: 产品名称 * product_tag: * type: string * description: 产品标签 * branch_version: * type: string * description: 分支版本 * publish_time: * type: string * description: 发布时间 * publish_user: * type: string * description: 发布人 * publish_status: * type: integer * description: 发布状态 * publish_type: * type: integer * description: 发布类型 * publish_env: * type: integer * description: 发布环境 * message: * type: string * description: 响应消息 */ exports.setPublishHistory = async (req: Request, res: Response) => { // 检查publish_record表中是否已存在相同的branch_version let recordData = await publish_record.findAll({ where: { branch_version: req.body.branch_version }, }); // 检查publish_info表中是否已存在相同的branch_version let infoData = await publish_info.findAll({ where: { branch_version: req.body.branch_version }, }); if ( new Date(req.body.publish_time).toLocaleString().slice(0, -3) < new Date().toLocaleString().slice(0, -3) ) { res.send({ success: false, message: "发布时间不能早于当前时间", error: "发布时间不能早于当前时间", }); return; } if (recordData.length || infoData.length) { res.send({ success: false, message: "该分支版本已存在发布记录,请勿重复发布", error: "该分支版本已存在发布记录,请勿重复发布", }); return; } changeReleaseTag(res, req.body); }; //associations.ts import publish_info from "./publish-info"; import publish_record from "./publish-record"; // 设置关联关系,通过主键id关联 // 添加 publish_info 到 publish_record 的反向关联 publish_info.belongsTo(publish_record, { foreignKey: "publishRecordId", targetKey: "id", onDelete: "SET NULL", onUpdate: "CASCADE", }); publish_record.hasMany(publish_info, { foreignKey: "publishRecordId", sourceKey: "id", onDelete: "SET NULL", onUpdate: "CASCADE", as: "products", }); export { publish_info as PublishInfo, publish_record as PublishRecord }; //publish-record/index.ts import sequelize from "../../mysql/index"; import publish_info from "../publish-info"; const { DataTypes } = require("sequelize"); const publish_record = sequelize.define( "publish_record", { id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, }, publish_user: { type: DataTypes.STRING, allowNull: false, }, branch_version: { type: DataTypes.STRING, allowNull: false, }, publish_status: { type: DataTypes.INTEGER, // 1: 待发布 2: 发布中 3:发布成功 4:发布失败 allowNull: false, defaultValue: 1, }, publish_time: { type: DataTypes.STRING, allowNull: false, }, publish_type: { type: DataTypes.INTEGER, // 1:手动发布 2:定时发布 allowNull: false, }, publish_env: { type: DataTypes.INTEGER, // 1:测试环境 2:生产环境 allowNull: false, }, }, { indexes: [ { fields: ["branch_version"], }, ], } ); // 使用alter选项更新表结构 publish_record.sync({ alter: true }); export default publish_record; //publish_info import sequelize from "../../mysql/index"; const { DataTypes } = require("sequelize"); const publish_info = sequelize.define( "publish_info", { id: { type: DataTypes.INTEGER, primaryKey: true, autoIncrement: true, }, product_name: { type: DataTypes.STRING, allowNull: false, }, product_tag: { type: DataTypes.STRING, allowNull: false, }, branch_version: { type: DataTypes.STRING, allowNull: false, }, // 添加外键字段,关联publish_record表的id publishRecordId: { type: DataTypes.INTEGER, allowNull: true, references: { model: "publish_records", // 使用表名而不是模型引用 key: "id", }, }, }, { indexes: [ { fields: ["branch_version"], }, ], } ); // 使用alter选项更新表结构 publish_info.sync({ alter: true }); export default publish_info; //main.ts const express = require("express"); const cors = require("cors"); const bodyParser = require("body-parser"); const app = express(); import swaggerDoc from "./swagger"; import "./model/associations"; // 开启允许跨域访问 app.use(cors()); app.use(express.static("public")); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.text()); app.use(bodyParser.raw()); app.use("/", require("./routes/index")); // 添加 Swagger 文档 swaggerDoc(app); app.listen(3003, () => { console.log("LP_Annotation_ConfigServer is running on port 3003"); }); 根据现有代码使用tsoa进行改造重构,可新增或修改文件
最新发布
09-17
在Web开发中,JSON(JavaScript Object Notation)被广泛用于配置文件、数据交换格式以及API通信。以下是一些与Web类型相关的JSON配置或定义的常见场景: ### 配置文件中的 JSON 使用 1. **`package.json`** `package.json` 是 Node.js 项目中的核心配置文件,用于定义项目元数据、依赖项、脚本命令等。 例如,以下是一个典型的 `package.json` 片段: ```json { "name": "my-web-app", "version": "1.0.0", "description": "A simple web application", "main": "index.js", "scripts": { "start": "node index.js", "build": "webpack --mode production" }, "dependencies": { "express": "^4.17.1" }, "devDependencies": { "webpack": "^5.0.0" } } ``` 2. **`tsconfig.json`** `tsconfig.json` 是 TypeScript 项目的配置文件,用于指定编译选项和项目结构。例如: ```json { "compilerOptions": { "target": "es5", "module": "esnext", "strict": true, "outDir": "./dist", "typeRoots": ["node_modules/@types"], "types": ["lodash"] }, "include": ["src/**/*"] } ``` 上述配置中,`typeRoots` 和 `types` 用于指定类型定义文件的位置,确保 TypeScript 能够正确识别第三方库的类型定义 [^2]。 3. **`webpack.config.json`** Webpack 是一个模块打包工具,其配置文件通常使用 JSON 或 JavaScript 编写。例如: ```json { "entry": "./src/index.js", "output": { "filename": "bundle.js", "path": "/dist" }, "module": { "rules": [ { "test": /\.js$/, "loader": "babel-loader" } ] } } ``` ### API 数据格式中的 JSON 使用 1. **RESTful API 响应格式** Web 应用程序通常使用 JSON 作为 API 响应格式。例如,一个获取用户信息的 API 可能返回如下 JSON: ```json { "id": 1, "name": "Alice", "email": "alice@example.com" } ``` 2. **GraphQL 查询和响应** GraphQL 是一种用于 API 的查询语言,其查询和响应通常使用 JSON 格式。例如,一个 GraphQL 查询: ```graphql query { user(id: 1) { name email } } ``` 对应的响应可能是: ```json { "data": { "user": { "name": "Alice", "email": "alice@example.com" } } } ``` ### 数据校验与模式定义 1. **JSON Schema** JSON Schema 是一种用于描述和校验 JSON 数据结构的规范。例如,以下是一个用于校验用户数据的 JSON Schema: ```json { "$schema": "http://json-schema.org/draft-07/schema#", "title": "User", "type": "object", "properties": { "id": { "type": "integer" }, "name": { "type": "string" }, "email": { "type": "string", "format": "email" } }, "required": ["id", "name"] } ``` 2. **Swagger/OpenAPI 配置** Swagger 或 OpenAPI 规范使用 JSON 或 YAML 来描述 RESTful API 的结构。例如,一个简单的 OpenAPI 配置片段: ```json { "openapi": "3.0.0", "info": { "title": "User API", "version": "1.0.0" }, "paths": { "/users": { "get": { "summary": "Get all users", "responses": { "200": { "description": "A list of users", "content": { "application/json": { "schema": { "type": "array", "items": { "$ref": "#/components/schemas/User" } } } } } } } } }, "components": { "schemas": { "User": { "type": "object", "properties": { "id": { "type": "integer" }, "name": { "type": "string" } } } } } } ``` ### Web 框架中的 JSON 配置 1. **Spring Boot 中的 `application.json`** Spring Boot 支持使用 JSON 格式来配置应用属性。例如: ```json { "server": { "port": 8080 }, "spring": { "datasource": { "url": "jdbc:mysql://localhost:3306/mydb", "username": "root", "password": "password" } } } ``` 在 Spring Boot 中,可以使用 `@JsonFormat` 和 `@DateTimeFormat` 注解来处理日期格式的序列化和反序列化 [^4]。 ### Web 开发中的 JSON 工具支持 1. **JSON 校验工具** 一些 IDE 和编辑器(如 VS Code)支持通过 `jsonValidation` 配置对 JSON 文件进行校验。例如,在 `package.json` 中可以配置 JSON 校验规则 [^1]。 2. **JSON 美化与解析工具** 开发者可以使用在线工具或库(如 `prettier`、`jsonlint`)来格式化和校验 JSON 数据。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值