bat脚本安装MySQL

bat脚本安装MySQL,注册Windows服务,设置root密码,新增用户,并执行脚本。此处用的MySQL5.7的压缩包版本。将MySQL移动到C:\ProgramData目录下,进行安装。

@echo off
setlocal enabledelayedexpansion

REM ====== 可配置参数 ======


set TARGET_PARENT=C:\ProgramData
set BASE_DIR=%TARGET_PARENT%\mysql_57


set INSTALL_DIR=%BASE_DIR%\mysql-5.7.44-winx64
set DATA_DIR=%INSTALL_DIR%\data
set MYSQL_SERVICE_NAME=MySQL57
set MYSQL_PORT=3306

set ROOT_PASSWORD=root
set APP_USER=user1
set APP_PASSWORD=userpwd

REM =========================


echo =====================================================
echo MySQL 5.7 Auto Install Script
echo =====================================================

REM ====== 1. 检测服务是否已存在 ======
echo Checking existing MySQL service...

sc query %MYSQL_SERVICE_NAME% >nul 2>&1
if %errorlevel% EQU 0 (
echo MySQL service "%MYSQL_SERVICE_NAME%" already exists.
echo Installation aborted to prevent overwrite.
exit /b 0
)


REM ====== 2. 检测系统中是否已有其他 MySQL 服务 ======
set "OTHER_MYSQL_FOUND="

REM 使用 tokens=2 抓取冒号后的实际名称,并过滤掉我们自己定义的服务名
for /f "tokens=2" %%s in ('sc query state^= all ^| findstr /I "SERVICE_NAME" ^| findstr /I "MySQL"') do (
    set "TEMP_SERVICE=%%s"
    if /I "!TEMP_SERVICE!" NEQ "%MYSQL_SERVICE_NAME%" (
        set "OTHER_MYSQL_FOUND=!TEMP_SERVICE!"
    )
)

if defined OTHER_MYSQL_FOUND (
    echo [ERROR] Another MySQL service detected: !OTHER_MYSQL_FOUND!
    echo Installation aborted.
    pause
    exit /b 0
)


REM ====== 3. 检测端口是否被占用 ======
echo Checking port %MYSQL_PORT%...

netstat -ano | findstr ":%MYSQL_PORT% " >nul
if %errorlevel% EQU 0 (
echo Port %MYSQL_PORT% is already in use.
echo Installation aborted.
exit /b 0
)




REM ====== 4. 目录迁移逻辑 (处理路径中的括号问题) ======
REM 使用引号包裹路径,防止 (x86) 导致脚本崩溃
set "CURRENT_DIR=%~dp0"
if /I "%CURRENT_DIR%" NEQ "%BASE_DIR%\" (
    echo Moving files to %BASE_DIR%...
    
    if not exist "%TARGET_PARENT%" mkdir "%TARGET_PARENT%"
    
    REM 复制当前目录到 ProgramData
    xcopy "%~dp0*" "%BASE_DIR%\" /E /I /Y /Q >nul
    
    if !errorlevel! EQU 0 (
        echo Files moved successfully. Relaunching...
        REM 关键:使用 pushd 切换环境,避免旧路径括号干扰
        pushd "%BASE_DIR%"
        start "" /D "%BASE_DIR%" "%BASE_DIR%\%~nx0"
        exit /b 0
    ) else (
        echo [ERROR] Failed to move files. Please run as Administrator.
        pause & exit /b 1
    )
)


echo ==== Creating my.ini ====

(
echo [mysqld]
echo basedir="%INSTALL_DIR%"
echo datadir="%DATA_DIR%"
echo port=%MYSQL_PORT%
echo character-set-server=utf8
echo default-storage-engine=INNODB
echo sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
echo max_connections=200
echo ssl=0
echo.
echo [client]
echo default-character-set=utf8
) > "%INSTALL_DIR%\my.ini"

echo ==== Initializing database ====

"%INSTALL_DIR%\bin\mysqld.exe" ^
--initialize-insecure ^
--basedir="%INSTALL_DIR%" ^
--datadir="%DATA_DIR%"

if errorlevel 1 (
echo MySQL initialize FAILED
exit /b 1
)

echo ==== Installing Windows Service ====

"%INSTALL_DIR%\bin\mysqld.exe" ^
--install %MYSQL_SERVICE_NAME% ^
--defaults-file="%INSTALL_DIR%\my.ini"

sc config %MYSQL_SERVICE_NAME% start= auto >nul

echo ==== Starting Service ====
net start %MYSQL_SERVICE_NAME%

timeout /t 5 >nul

echo ==== Configuring Firewall ====

netsh advfirewall firewall show rule name="MySQL57 3306" >nul 2>&1
if %errorlevel% NEQ 0 (
    netsh advfirewall firewall add rule name="MySQL57 3306" dir=in action=allow protocol=TCP localport=%MYSQL_PORT%
    echo Firewall rule added
) else (
    echo Firewall rule already exists
)

echo ==== Setting root password ====

"%INSTALL_DIR%\bin\mysqladmin.exe" ^
-u root password "%ROOT_PASSWORD%"

echo ==== Creating user and privileges ====

"%INSTALL_DIR%\bin\mysql.exe" ^
-u root -p%ROOT_PASSWORD% ^
-e "CREATE USER '%APP_USER%'@'%%' IDENTIFIED BY '%APP_PASSWORD%';"

"%INSTALL_DIR%\bin\mysql.exe" ^
-u root -p%ROOT_PASSWORD% ^
-e "GRANT ALL PRIVILEGES ON *.* TO '%APP_USER%'@'%%' WITH GRANT OPTION; FLUSH PRIVILEGES;"

echo ==== Executing SQL scripts ====

"%INSTALL_DIR%\bin\mysql.exe" -u root -p%ROOT_PASSWORD% < "%BASE_DIR%\sql\init1.sql"

"%INSTALL_DIR%\bin\mysql.exe" -u root -p%ROOT_PASSWORD% < "%BASE_DIR%\sql\init2.sql"

echo ==== MySQL 5.7 Installed Successfully ====
exit /b 0

docker mysql 没有 root 用户

docker mysql 没有 root 用户,需要创建 root

  1. flush privileges; 解决 ERROR 1290 (HY000): The MySQL server is running with the –skip-grant-tables option so it cannot execute 这个问题
  2. CREATE USER ‘root’@’%’ IDENTIFIED WITH mysql_native_password BY ‘123’;
  3. GRANT ALL PRIVILEGES ON *.* TO ‘root’@’%’ WITH GRANT OPTION;
  4. flush privileges;

mysql8 Public Key Retrieval is not allowed

mysql8 之后,用户的密码验证改为caching_sha2_password,MySQL5.7及之前为mysql_native_password。

方法一:

登录MySQL后输入:

ALTER USER ‘your user name’@’your host’ IDENTIFIED WITH mysql_native_password BY ‘YourPassword’;

FLUSH PRIVILEGES;

方法二:

编辑my.cnf文件,更改默认的身份认证插件。

vi /etc/my.cnf

在[mysqld]中添加下边的代码
default_authentication_plugin=mysql_native_password

然后重启MySQL

批量 修改 数据库的字符集和排序规则

-- 字符集为utf8mb4,排序规则为utf8mb4_unicode_ci

-- 修改数据库
ALTER DATABASE 数据库名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 设置每张表的字符集和排序规则为为 utf8mb4、utf8mb4_unicode_ci
SELECT CONCAT('ALTER TABLE ', table_name, ' CONVERT TO CHARACTER SET  utf8mb4 COLLATE utf8mb4_unicode_ci;')
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = '数据库名';

-- 批量修改字符编码和排序编码
select concat('ALTER TABLE `', table_name, '` MODIFY `', column_name, '`', DATA_TYPE, '(', CHARACTER_MAXIMUM_LENGTH,
              ') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci', ';')
FROM information_schema.COLUMNS
WHERE table_schema = '数据库名'
  AND DATA_TYPE IN ('varchar' ,'char');

mysql 查询结果被 截断 问题 group_concat

前几天在项目中遇到一个问题,使用 GROUP_CONCAT 函数select出来的数据被截断了,最长长度不超过1024字节,开始还以为是客户端自身对字段长度做了限制的问题。后来查找出原因

1 查找原因

至此,只能从SQL语句出发了。网上搜了下 GROUP_CONCAT 数据截断的问题,答案都指向了 group_concat_max_len 这个参数,它的默认值正好是1024。可以直接在数据库中通过下面的命令查看这个默认值:

mysql> show variables like 'group_concat_max_len';
Variable_name  | Value |
-|group_concat_max_len | 1024 |

MySQL官方手册 对它的定义是 The maximum permitted result length in bytes for the GROUP_CONCAT() function. ,也就是它限制了 GROUP_CONCAT 数据的长度。

如果是生产环境下,不能擅自重启MySQL服务,则可以通过语句设置group_concat的作用范围,如:

 SET GLOBAL group_concat_max_len=2048;

 SET SESSION group_concat_max_len=2048;

MySQL sql_mode=only_full_group_by 错误

SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'blog.categories.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

MySQL 有时会遇到这种问题,后来网上查了一下据库版本为 5.7 以上的版本,默认是开启了 only_full_group_by 模式的,但开启这个模式后,原先的 group by 语句就报错。

原因:

其中 ONLY_FULL_GROUP_BY 就是造成这个错误的原因,

对于 group by 聚合操作,如果在 select 中的列没有在 group by 中出现,那么这个 SQL 是不合法的,因为列不在 group by 从句中,所以设置了 sql_mode=only_full_group_by 的数据库,在使用 group by 时就会报错。

Mysql自定义函数报错解决方法

在MySql中创建自定义函数报错信息如下:

ERROR 1418 (HY000): This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you *might* want to use the less safe log_bin_trust_function_creators variable)

解决方法:

mysql>set global log_bin_trust_function_creators=1;

MySQL 中的 timestamp 和 datetime

两者都可用来表示YYYY-MM-DD HH:MM:SS[.fraction]类型的日期。

对于TIMESTAMP,它把客户端插入的时间从当前时区转化为UTC(世界标准时间)进行存储。查询时,将其又转化为客户端当前时区进行返回。

而对于DATETIME,不做任何改变,基本上是原样输入和输出。

timestamp所能存储的时间范围为:’1970-01-01 00:00:01.000000′ 到 ‘2038-01-19 03:14:07.999999’。

datetime所能存储的时间范围为:’1000-01-01 00:00:00.000000′ 到 ‘9999-12-31 23:59:59.999999’。

在MySQL 5.6.5版本之前,Automatic Initialization and Updating只适用于TIMESTAMP,而且一张表中,最多允许一个TIMESTAMP字段采用该特性。从MySQL 5.6.5开始,Automatic Initialization and Updating同时适用于TIMESTAMP和DATETIME,且不限制数量。

ps: 自动初始化和自动更新(Automatic Initialization and Updating)

自动初始化指的是如果对该字段(譬如上例中的hiredate字段)没有显性赋值,则自动设置为当前系统时间。

自动更新指的是如果修改了其它字段,则该字段的值将自动更新为当前系统时间。

设置自动修改时间:

–添加UpdateTime 设置 默认时间 CURRENT_TIMESTAMP   设置更新时间为 ON UPDATE CURRENT_TIMESTAMP 
ALTER TABLE table_name
ADD COLUMN UpdateTime datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘创建时间’ ;

TIMESTAMP(3)与 DATETIME(3)意思是保留3为毫秒数

TIMESTAMP(6)与 DATETIME(6)意思是保留6为毫秒数