For the complete documentation index, see llms.txt. This page is also available as Markdown.
QUẢN LÝ TRẠM
Một số phiên bản cũ chưa có bảng kiểm tra trạm đăng nhập
KIỂM TRA TRẠM, USER ĐANG NHẬP
Nhìn vào thời gian nào đăng nhập xa nhất, thì có thể là trạm đó không sử dụng. Báo lại khách hàng kiểm tra user đó còn hoạt động hay không để xử lý tiếp
with cte_lichsu as (select ComputerName as tenmaytinh, CreateDate as ngayTao,tram, [user] as userDangnhap , ROW_NUMBER() over(partitionby tram order by createdate desc) as sttFrom chamcongwhere CreateDate>='01/01/2025'--- chặn thời gian cho phù hợp. )select cte_lichsu.*, users.tenfrom cte_lichsu inner join [users] oncte_lichsu.userDangnhap=[users].[user]wherecte_lichsu.stt=1order by tram------------------ code dưới không sử dụng. vì không chuẩn-------- Liệt kê các trạm đăng nhậpselect T1.*, T2.tenfrom(selectmax(computername) as tenmaytinh,max(noidung) as noidung,max(createdate) as thoigian,max([user]) as nguoidung, tram From chamcong --WHERE NOIDUNG LIKE N'%thuỷ%' -- where thêm ở nội dung sẽ chuẩn hơnGroup by tram)T1 inner join(select [user] as nguoidung,*from [users])T2 onT1.nguoidung=T2.nguoidungOrder by thoigian des
TRẠM ĐĂNG NHẬP BẢN DỊCH VỤ
Danh sách tất cả các database và trạm thỏa mãn điều kiện
Danh sách các trạm thỏa mãn điều kiện:
RESET ID TRẠM BẢN DEV Cũ
TRƯỜNG HỢP CÓ CẢ DATABASE BẢN DEV CŨ VÀ DEV MỚI thì cần lọc theo tên thư mục cài đặt để reset
CẬP NHẬT ĐƯỜNG DẪN BACKUP TẤT CẢ CÁC DATABASE BẢN DỊCH VỤ
DECLARE @DBName NVARCHAR(128);
DECLARE @SQL NVARCHAR(MAX) = N'';
DECLARE @CheckSQL NVARCHAR(MAX);
DECLARE @IsTargetDB INT;
-- 1. Quét các Database đang Online và không phải DB hệ thống
DECLARE db_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT name
FROM sys.databases
WHERE database_id > 4 AND state = 0;
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO @DBName;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @IsTargetDB = 0;
-- 2. KIỂM TRA CẤU TRÚC VÀ ĐIỀU KIỆN THÔNG TƯ ĐẦU VÀO
-- Lớp 1: Kiểm tra sự tồn tại của bảng và cột để tránh lỗi biên dịch (Compile Error)
-- Lớp 2: Kiểm tra xem ThongTuApp có thuộc danh sách '88' hoặc '152' không
SET @CheckSQL = N'
SET @Result = 0;
IF OBJECT_ID(N''[' + @DBName + N'].dbo.CustomsInfor'') IS NOT NULL
AND EXISTS (SELECT 1 FROM [' + @DBName + N'].sys.columns WHERE object_id = OBJECT_ID(N''[' + @DBName + N'].dbo.CustomsInfor'') AND name = ''ThongTuApp'')
AND OBJECT_ID(N''[' + @DBName + N'].dbo.chamcong'') IS NOT NULL
AND OBJECT_ID(N''[' + @DBName + N'].dbo.users'') IS NOT NULL
BEGIN
-- Thực thi SQL động cấp 2: Dùng IN để lọc cùng lúc nhiều thông tư
DECLARE @InnerSQL NVARCHAR(MAX) = N''IF EXISTS (SELECT 1 FROM [' + @DBName + N'].dbo.CustomsInfor WHERE ThongTuApp IN (''''88'''', ''''152'''')) SET @Match = 1;'';
EXEC sp_executesql @InnerSQL, N''@Match INT OUTPUT'', @Match = @Result OUTPUT;
END';
-- Thực thi lệnh kiểm tra và gán kết quả vào @IsTargetDB
EXEC sp_executesql @CheckSQL, N'@Result INT OUTPUT', @Result = @IsTargetDB OUTPUT;
-- 3. NẾU DATABASE NÀY HỢP LỆ (Thỏa mãn 1 trong 2 thông tư) -> Tiến hành nối chuỗi UNION ALL
IF @IsTargetDB = 1
BEGIN
SET @SQL = @SQL +
N'SELECT ''' + @DBName + N''' AS TenDatabase, ' +
-- Thêm cột hiển thị thông tư thực tế của database để bạn dễ quản lý, theo dõi
N' (SELECT TOP 1 ThongTuApp FROM [' + @DBName + N'].dbo.CustomsInfor) AS ThongTuApDung, ' +
N' c.tenmaytinh, c.ngayTao, c.tram, c.userDangnhap, u.ten ' +
N'FROM ( ' +
N' SELECT ComputerName AS tenmaytinh, CreateDate AS ngayTao, tram, [user] AS userDangnhap, ' +
N' ROW_NUMBER() OVER(PARTITION BY tram ORDER BY CreateDate DESC) AS stt ' +
N' FROM [' + @DBName + N'].dbo.chamcong ' +
N' WHERE CreateDate >= ''20250101'' ' +
N') c ' +
N'INNER JOIN [' + @DBName + N'].dbo.[users] u ON c.userDangnhap = u.[user] ' +
N'WHERE c.stt = 1 ' +
N'UNION ALL ' + CHAR(13) + CHAR(10);
END
FETCH NEXT FROM db_cursor INTO @DBName;
END
CLOSE db_cursor;
DEALLOCATE db_cursor;
-- 4. Chạy câu lệnh tổng hợp
IF LEN(@SQL) > 0
BEGIN
-- Cắt bỏ chữ 'UNION ALL ' và ký tự xuống dòng ở cuối chuỗi
SET @SQL = LEFT(@SQL, LEN(@SQL) - 12);
-- Sắp xếp theo Tên Database, Thông tư áp dụng và Tên trạm
SET @SQL = @SQL + N' ORDER BY TenDatabase, ThongTuApDung, tram;';
-- Bạn có thể mở comment dòng PRINT dưới đây để kiểm tra cấu trúc câu lệnh hoàn chỉnh trước khi thực thi
-- PRINT CAST(@SQL AS NTEXT);
EXEC sp_executesql @SQL;
END
ELSE
BEGIN
PRINT N'Không tìm thấy cơ sở dữ liệu nào áp dụng Thông tư 88 hoặc 152.';
END
DECLARE @DBName NVARCHAR(128);
DECLARE @SQL NVARCHAR(MAX) = N'';
DECLARE @CheckSQL NVARCHAR(MAX);
DECLARE @IsTargetDB INT;
-- 1. Quét các Database
DECLARE db_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT name
FROM sys.databases
WHERE database_id > 4 AND state = 0;
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO @DBName;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @IsTargetDB = 0;
-- 2. Kiểm tra điều kiện Database (Chứa bảng/cột và ThongTuApp = 88 hoặc 152)
SET @CheckSQL = N'
SET @Result = 0;
IF OBJECT_ID(N''[' + @DBName + N'].dbo.CustomsInfor'') IS NOT NULL
AND EXISTS (SELECT 1 FROM [' + @DBName + N'].sys.columns WHERE object_id = OBJECT_ID(N''[' + @DBName + N'].dbo.CustomsInfor'') AND name = ''ThongTuApp'')
AND OBJECT_ID(N''[' + @DBName + N'].dbo.chamcong'') IS NOT NULL
AND OBJECT_ID(N''[' + @DBName + N'].dbo.users'') IS NOT NULL
BEGIN
DECLARE @InnerSQL NVARCHAR(MAX) = N''IF EXISTS (SELECT 1 FROM [' + @DBName + N'].dbo.CustomsInfor WHERE ThongTuApp IN (''''88'''', ''''152'''')) SET @Match = 1;'';
EXEC sp_executesql @InnerSQL, N''@Match INT OUTPUT'', @Match = @Result OUTPUT;
END';
EXEC sp_executesql @CheckSQL, N'@Result INT OUTPUT', @Result = @IsTargetDB OUTPUT;
-- 3. Ghép chuỗi truy vấn: Đã bỏ các cột Tên Database và Thông tư
IF @IsTargetDB = 1
BEGIN
SET @SQL = @SQL +
N'SELECT c.tenmaytinh, c.ngayTao, c.tram, c.userDangnhap, u.ten ' +
N'FROM ( ' +
N' SELECT ComputerName AS tenmaytinh, CreateDate AS ngayTao, tram, [user] AS userDangnhap, ' +
N' ROW_NUMBER() OVER(PARTITION BY tram ORDER BY CreateDate DESC) AS stt ' +
N' FROM [' + @DBName + N'].dbo.chamcong ' +
N' WHERE CreateDate >= ''20250101'' ' +
N') c ' +
N'INNER JOIN [' + @DBName + N'].dbo.[users] u ON c.userDangnhap = u.[user] ' +
N'WHERE c.stt = 1 ' +
N'UNION ALL ' + CHAR(13) + CHAR(10);
END
FETCH NEXT FROM db_cursor INTO @DBName;
END
CLOSE db_cursor;
DEALLOCATE db_cursor;
-- 4. Bọc toàn bộ chuỗi SQL vào một CTE lớn và lọc lại lần cuối trên toàn hệ thống
IF LEN(@SQL) > 0
BEGIN
-- Cắt bỏ chữ 'UNION ALL ' ở cuối chuỗi
SET @SQL = LEFT(@SQL, LEN(@SQL) - 12);
-- Khởi tạo câu lệnh Final bằng cách bọc @SQL vào bên trong
DECLARE @FinalSQL NVARCHAR(MAX) = N'
WITH AllDB_Data AS (
' + @SQL + N'
),
Global_Rank AS (
SELECT tenmaytinh, ngayTao, tram, userDangnhap, ten,
ROW_NUMBER() OVER(PARTITION BY tram ORDER BY ngayTao DESC) AS global_stt
FROM AllDB_Data
)
SELECT tenmaytinh, ngayTao, tram, userDangnhap, ten
FROM Global_Rank
WHERE global_stt = 1
ORDER BY tram,ngayTao DESC;'; -- Ưu tiên hiển thị các đăng nhập mới nhất lên trên cùng
-- PRINT CAST(@FinalSQL AS NTEXT); -- Kiểm tra chuỗi sinh ra nếu cần
EXEC sp_executesql @FinalSQL;
END
ELSE
BEGIN
PRINT N'Không tìm thấy cơ sở dữ liệu nào áp dụng Thông tư 88 hoặc 152.';
END
--ÁP DỤNG CHO BẢN DEV CŨ KHÔNG CÓ RESET NHIỀU DATABASE
-- CHÚ Ý CHỈ ÁP DỤNG CHO MÁY CHỈ CÓ RIÊNG BẢN KẾ TOÁN DEV CŨ,
--Nếu có cả DEV mới và 88 thì không dùng được
--1. Kiểm tra danh sách các database
SELECT name,database_id FROM sys.databases
WHERE database_id>6 -- Lấy ra Vị trí của database bắt đầu dùng DTECH, lại đi các db của hệ thống (master, model,msdb,tempdb,report...)
--2. Dựa theo vị trí để điền lại vào @id_data
DECLARE @vitri int -- Vị trí những mã trống theo thứ tự tăng dần
DECLARE @tendb NVARCHAR(300)
DECLARE @id_tram INT
DECLARE @id_data INT
DECLARE @sql_cmm NVARCHAR(MAX)
Declare @err_state int =0; -- Trạng thái lỗi trả về
SET @id_tram =1 -- ID trạm cần reset
SET @id_data = 7 -- Vị trí id của database bắt đầu dùng DTECH
--Tạo 1 bảng tạm quét danh sách các database
declare bangdsdata cursor for
select ROW_NUMBER() OVER(ORDER BY name ASC) AS vitri,name from sys.databases where database_id>=@id_data
open bangdsdata
Fetch next from bangdsdata
into @vitri,@tendb
While @@FETCH_STATUS=0
BEGIN
print '--vitri: '+ CONVERT(NVARCHAR,@vitri)
--print 'Ma: '+@kytu+FORMAT(@maxso+@vitri,'00000')
--PRINT 'Update: '+'Update ['+@tendb+'].dbo.Tram set trangthai=0,modidate=getdate() where tram='+CONVERT(NVARCHAR,@id_tram)
SET @sql_cmm='Update ['+@tendb+'].dbo.Tram set trangthai=0,modidate=getdate() where tram='+CONVERT(NVARCHAR,@id_tram)
BEGIN TRY
PRINT @sql_cmm
EXEC(@sql_cmm)
END TRY
BEGIN CATCH
SELECT @err_state = ERROR_STATE()
END CATCH;
Fetch next from bangdsdata
into @vitri,@tendb
END
CLOSE bangdsdata
DEALLOCATE bangdsdata
--0. Kiểm tra danh sách các database
SELECT T1.name,T1.database_id,T2.physical_name
FROM sys.databases T1
join sys.master_files T2
on T1.database_id = T2.database_id
WHERE T2.type_desc = 'ROWS'
and Charindex(N'\DtechService\',T2.physical_name)>0
---------------------------------------------------------
--1. Khai báo các tham số
DECLARE @vitri INT -- Vị trí thứ tự tăng dần
DECLARE @tendb NVARCHAR(300)
DECLARE @id_tram INT
DECLARE @sql_cmm NVARCHAR(MAX)
DECLARE @err_state INT = 0; -- Trạng thái lỗi trả về
SET @id_tram = 4 -- ID trạm cần reset
-- 2. Sửa Cursor để duyệt qua danh sách database thỏa mãn điều kiện đường dẫn vật lý
DECLARE bangdsdata CURSOR FOR
SELECT
ROW_NUMBER() OVER(ORDER BY T1.name ASC) AS vitri,
T1.name
FROM sys.databases T1
JOIN sys.master_files T2 ON T1.database_id = T2.database_id
WHERE T2.type_desc = 'ROWS' -- Chỉ lấy file dữ liệu, tránh lấy file LOG
AND CHARINDEX(N'\DtechService\', T2.physical_name) > 0
OPEN bangdsdata
FETCH NEXT FROM bangdsdata INTO @vitri, @tendb
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT N'-- Đang xử lý vị trí: ' + CONVERT(NVARCHAR, @vitri) + ' | Database: ' + @tendb
-- Xây dựng câu lệnh Update động
SET @sql_cmm = 'UPDATE [' + @tendb + '].dbo.Tram SET trangthai = 0, modidate = GETDATE() WHERE tram = ' + CONVERT(NVARCHAR, @id_tram)
BEGIN TRY
PRINT N'Lệnh thực thi: ' + @sql_cmm
--EXEC(@sql_cmm)
END TRY
BEGIN CATCH
PRINT N'Lỗi tại Database: ' + @tendb
SELECT @err_state = ERROR_STATE()
END CATCH;
FETCH NEXT FROM bangdsdata INTO @vitri, @tendb
END
CLOSE bangdsdata
DEALLOCATE bangdsdata
--ÁP DỤNG CHO BẢN DEV CŨ KHÔNG CÓ RESET NHIỀU DATABASE
-- CHÚ Ý CHỈ ÁP DỤNG CHO MÁY CHỈ CÓ RIÊNG BẢN KẾ TOÁN DEV CŨ,
--1. Kiểm tra danh sách các database
SELECT name,database_id FROM sys.databases
WHERE database_id>4 -- Lấy ra Vị trí của database bắt đầu dùng DTECH, lại đi các db của hệ thống (master, model,msdb,tempdb,report...)
--2. Dựa theo vị trí để điền lại vào @id_data
DECLARE @vitri int -- Vị trí những mã trống theo thứ tự tăng dần
DECLARE @tendb NVARCHAR(300)
DECLARE @id_tram INT
DECLARE @id_data INT
DECLARE @sql_cmm NVARCHAR(MAX)
Declare @err_state int =0; -- Trạng thái lỗi trả về
DECLARE @path NVARCHAR(MAX)
DECLARE @value NVARCHAR(MAX)
SET @path=N'E:\DTECH\DtechService\Backup' -- Đường dẫn backup SQL
SET @value =N'SelectedPath'
--SET @id_tram =1 -- ID trạm cần reset
SET @id_data = 5 -- Vị trí id của database bắt đầu dùng DTECH
--Tạo 1 bảng tạm quét danh sách các database
declare bangdsdata cursor for
select ROW_NUMBER() OVER(ORDER BY name ASC) AS vitri,name from sys.databases where database_id>=@id_data
open bangdsdata
Fetch next from bangdsdata
into @vitri,@tendb
While @@FETCH_STATUS=0
BEGIN
print '--vitri: '+ CONVERT(NVARCHAR,@vitri)
--print 'Ma: '+@kytu+FORMAT(@maxso+@vitri,'00000')
--PRINT 'Update: '+'Update ['+@tendb+'].dbo.Tram set trangthai=0,modidate=getdate() where tram='+CONVERT(NVARCHAR,@id_tram)
--SET @sql_cmm='Update ['+@tendb+'].dbo.Tram set trangthai=0,modidate=getdate() where tram='+CONVERT(NVARCHAR,@id_tram)
SET @sql_cmm='Update ['+@tendb+'].dbo.Dregistry set value='''+@path+''' where name='''+@value+''''
BEGIN TRY
PRINT @sql_cmm
EXEC(@sql_cmm)
END TRY
BEGIN CATCH
SELECT @err_state = ERROR_STATE()
END CATCH;
Fetch next from bangdsdata
into @vitri,@tendb
END
CLOSE bangdsdata
DEALLOCATE bangdsdata