CREATE TABLE users (
user_id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
uuid CHAR(36) NOT NULL UNIQUE,
username VARCHAR(50) NOT NULL UNIQUE,
password_hash CHAR(97) NOT NULL COMMENT 'argon2格式',
email VARCHAR(100) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE users ADD COLUMN data_version INT NOT NULL DEFAULT 0;
CREATE TABLE user_status_history (
log_id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL,
old_status ENUM('active','locked','deleted'),
new_status ENUM('active','locked','deleted'),
changed_by INT UNSIGNED,
change_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(user_id)
);
CREATE TABLE password_policies (
policy_id TINYINT PRIMARY KEY,
min_length TINYINT DEFAULT 8,
require_upper boolean DEFAULT true,
require_special CHAR (10)DEFAULT '!@#$%^&*'
);
CREATE INDEX idx_user_search ON users (last_name, first_name)
INCLUDE (email, phone);
CREATE INDEX idx_email_domain ON users((SUBSTRING_INDEX(email, '@', -1)));
ALTER TABLE user_profiles
ADD FULLTEXT ft_idx_bio (bio) WITH PARSER ngram;
ALTER TABLE users
ADD COLUMN geolocation POINT SRID 4326,
ADD SPATIAL INDEX idx_geo (geolocation);
DELIMITER $$
CREATE PROCEDURE RegisterUser(
IN p_username VARCHAR(50),
IN p_password VARCHAR(100),
IN p_email VARCHAR(100)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
INSERT INTO users (username, password_hash, email)
VALUES (p_username, argon2_hash(p_password), p_email);
INSERT INTO user_roles (user_id, role_id)
VALUES (LAST_INSERT_ID(), 2);
COMMIT;
END$$
DELIMITER ;
CREATE PROCEDURE ResetPassword(
IN p_user_id INT,
IN p_new_password VARCHAR(100)
)
SQL SECURITY INVOKER
BEGIN
UPDATE users
SET password_hash = argon2_hash(p_new_password),
data_version = data_version + 1
WHERE user_id = p_user_id
AND status = 'active';
END;
CREATE TRIGGER tr_password_change
AFTER UPDATE ON users
FOR EACH ROW
BEGIN
IF OLD.password_hash <> NEW.password_hash THEN
INSERT INTO security_logs
(user_id, event_type, details)
VALUES (NEW.user_id, 'PASSWORD_CHANGE',
CONCAT('Changed by ', USER()));
END IF;
END;
CREATE TRIGGER tr_prevent_user_delete
BEFORE DELETE ON users
FOR EACH ROW
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Use soft delete procedure instead';
CREATE VIEW v_user_details AS
SELECT u.*, p.phone, p.avatar_url,
GROUP_CONCAT(r.role_name) AS roles
FROM users u
LEFT JOIN user_profiles p ON u.user_id = p.user_id
LEFT JOIN user_roles ur ON u.user_id = ur.user_id
LEFT JOIN roles r ON ur.role_id = r.role_id
GROUP BY u.user_id;
CREATE VIEW v_active_users AS
SELECT DATE(login_time) AS login_date,
COUNT(DISTINCT user_id) AS active_users
FROM login_logs
WHERE success = TRUE
GROUP BY login_date;
INSERT INTO users (username, email, password_hash)
SELECT CONCAT('user', n),
CONCAT('user', n, '@test.com'),
argon2_hash(CONCAT('pass', n))
FROM (SELECT 1 + units.i + tens.i * 10 AS n
FROM (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units,
(SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens) numbers
WHERE n BETWEEN 1 AND 100;
UPDATE users
SET status = 'deleted',
username = CONCAT('deleted_', username),
email = CONCAT('deleted_', email)
WHERE user_id = ?;
CREATE USER 'report_user'@'%' IDENTIFIED BY 'SecurePass123!';
GRANT SELECT ON user_management.* TO 'report_user'@'%';
CREATE POLICY user_access_policy
ON users
FOR ALL
TO api_user
USING (user_id = current_user_id());
DELETE FROM login_logs
WHERE login_time < NOW() - INTERVAL 180 DAY
ORDER BY login_time LIMIT 1000;
ALTER TABLE users ENGINE=InnoDB;
ANALYZE TABLE users;
ALTER TABLE users ADD COLUMN metadata JSON;
SELECT user_id, metadata->'$.subscription.type'
FROM users WHERE metadata->'$.preferences.dark_mode' = 'true';
CREATE (u:User {userId: 1001, username: 'john_doe'})
CREATE (r:Role {name: 'Admin'})
CREATE (u)-[:HAS_ROLE]->(r)