FiveM MySQL Column Cannot Be Null Error 1048 แก้อย่างไร? วิธีแก้ NULL, NOT NULL, INSERT และ Schema ให้ตรง Resource
ปัญหา FiveM MySQL/MariaDB ขึ้น Column cannot be null หรือ Error 1048 เกิดเมื่อ Resource พยายามบันทึกค่า NULL ลงใน Column ที่ Database กำหนดว่า ห้ามเป็น NULL ทำให้คำสั่ง INSERT หรือ UPDATE ถูกปฏิเสธ
ตัวอย่าง Error ที่พบได้ เช่น:
ERROR 1048 (23000): Column 'identifier' cannot be null
Column 'citizenid' cannot be null
Column 'owner' cannot be null
Column 'plate' cannot be null
ER_BAD_NULL_ERROR
MariaDB ระบุ Error 1048, SQLSTATE 23000 เป็น ER_BAD_NULL_ERROR พร้อมข้อความ Column '%s' cannot be null โดยตรง.
ใน FiveM ปัญหานี้มักเกี่ยวกับระบบสำคัญ เช่น:
Character Creation
Player Identifier
Vehicle Ownership
Garage
Phone
Banking
Inventory
Housing
Business
Billing
Jobs
Whitelist
Ban System
จุดสำคัญคือ อย่าแก้ Error 1048 ด้วยการเปลี่ยนทุก Column ให้รับ NULL เพราะ Column บางตัวถูกกำหนด NOT NULL ด้วยเหตุผลสำคัญ เช่นต้องรู้ว่า Vehicle เป็นของใคร หรือ Character มี ID อะไร
วิธีแก้ที่ถูกต้องคือ:
อ่านชื่อ Column → หา Query → ดูว่าทำไม Resource ส่ง NULL → ตรวจ Schema → ตรวจ Resource Version/Migration → แก้ต้นเหตุ
① Error 1048 คืออะไร
MariaDB Error 1048 หมายถึงมีการพยายามส่ง NULL เข้า Column ที่ไม่อนุญาตให้เป็น NULL.
② ตัวอย่างง่ายที่สุด
สมมติ Table มี:
CREATE TABLE players (
id INT AUTO_INCREMENT PRIMARY KEY,
identifier VARCHAR(100) NOT NULL
);
แต่ Query ส่ง:
INSERT INTO players (identifier)
VALUES (NULL);
Database สามารถ Reject ได้ด้วย:
Column 'identifier' cannot be null
ตามกฎของ NOT NULL.
③ NULL คืออะไร
NULL หมายถึงไม่มีค่าหรือไม่ทราบค่าในเชิง Database และ MariaDB จัดการ NULL แตกต่างจากค่าปกติ.
④ NULL ไม่ใช่เลข 0
NULL
ไม่เหมือน:
0
⑤ NULL ไม่ใช่ String ว่าง
NULL
ไม่เหมือน:
''
การเปลี่ยน NULL เป็น '' เพียงเพื่อให้ Query ผ่านอาจทำให้ความหมายของข้อมูลผิดได้
⑥ NULL ไม่ใช่คำว่า "NULL"
สามค่านี้ต่างกัน:
NULL
'NULL'
''
ตัวแรกคือ SQL NULL ส่วนอีกสองค่าเป็น String.
⑦ NOT NULL คืออะไร
NOT NULL ใช้บังคับว่า Column ต้องมีค่าที่ไม่ใช่ NULL และ MariaDB จะแจ้ง Error 1048 เมื่อมีการ Insert NULL เข้า Column ลักษณะนี้.
⑧ ทำไม FiveM Database ต้องมี NOT NULL
เพราะข้อมูลบางประเภทจำเป็นต่อการระบุ Record เช่น:
Character Identifier
Vehicle Owner
Item Owner
Transaction Reference
การไม่มีค่าอาจทำให้ System ไม่สามารถเชื่อมข้อมูลได้อย่างถูกต้อง
⑨ Error 1048 เป็น Connection Error หรือไม่
ไม่ใช่
ถ้า MariaDB สามารถตอบ:
Column cannot be null
ได้ แสดงว่า Query ไปถึง Database และถูกตรวจแล้ว.
⑩ จึงไม่ควรเริ่มจากเปลี่ยน Password
ถ้า Error คือ 1048 ให้ตรวจ:
Query
Parameters
Data Flow
ก่อน
⑪ ไม่ต้องเปิด Port 3306 ใหม่
เพราะ Database ได้รับ Query แล้ว
⑫ Clear FiveM Cache ช่วยไหม
โดยทั่วไปไม่ใช่จุดแก้ของ Error 1048 เพราะปัญหาเกิดจากค่าที่ Resource ส่งเข้า Database
⑬ Restart MariaDB ช่วยไหม
ถ้า Query ยังส่ง NULL แบบเดิม:
Error จะกลับมา
⑭ Restart FiveM ช่วยไหม
ไม่แก้ Root Cause เช่นกัน เว้นแต่คุณแก้ Resource แล้วต้อง Reload Code ใหม่
⑮ Error identifier cannot be null
เป็น Error ที่ต้องระวังมาก
เพราะ Identifier อาจเป็นข้อมูลหลักที่เชื่อม Player กับ Character
⑯ ทำไม identifier กลายเป็น NULL
ตัวอย่างสาเหตุ:
Resource อ่าน Identifier ไม่ได้
Variable ผิดชื่อ
Framework Bridge ผิด
Event Payload ไม่มีข้อมูล
Resource Version ไม่ตรง
⑰ อย่าเปลี่ยน identifier ให้รับ NULL เพื่อให้หาย
เพราะ Record ที่ไม่มี Identifier อาจไม่สามารถระบุว่าเป็นของ Player คนใดได้
⑱ อย่าเปลี่ยน NULL เป็น Empty String แบบสุ่ม
ถ้า Character หลายตัวกลายเป็น:
identifier = ''
อาจเกิดปัญหา Mapping หรือ Unique Constraints ตาม Schema ภายหลัง
⑲ Error citizenid cannot be null
ควรตรวจ Character ID Generation
เช่น Resource ควรสร้าง:
citizenid
ก่อน Insert Character แต่ Function ที่สร้าง ID ไม่คืนค่า
⑳ ตรวจ Variable จริงก่อน Query
เช่น:
citizenId = nil
หรือ JavaScript:
citizenId = null
แล้วถูกส่งต่อเข้าฐานข้อมูล
㉑ Lua nil กับ SQL NULL
ใน Database Wrapper บาง Flow ค่า nil ที่ถูกส่งเป็น Parameter อาจทำให้ปลายทางกลายเป็น NULL หรือทำให้ Parameter ขาด ขึ้นอยู่กับ API ที่ใช้
ดังนั้นให้ดู Query/Parameters จริงจาก Resource
㉒ JavaScript null ก็ต้องระวัง
เช่น:
const owner = null;
แล้วส่งเข้า:
INSERT INTO vehicles (owner) VALUES (?)
ถ้า owner เป็น NOT NULL:
Query ไม่ควรผ่าน
㉓ undefined ต่างจาก null
ใน JavaScript:
undefined
กับ:
null
เป็นคนละ State ใน Application
Database Wrapper อาจ Handle ต่างกัน จึงควรตรวจค่าก่อน Query
㉔ Server-side Validation สำคัญ
ก่อน Insert ควรถาม:
owner มีค่าหรือไม่?
citizenid มีค่าหรือไม่?
plate มีค่าหรือไม่?
ถ้าไม่มี ไม่ควรส่ง Query ต่ออย่างเงียบ ๆ
㉕ Error owner cannot be null
พบได้ในระบบ:
Vehicle
Property
Business
Inventory
㉖ Vehicle Owner เป็น NULL อันตรายอย่างไร
Owned Vehicle อาจไม่สามารถเชื่อมกับ Character ที่ซื้อรถ
จึงไม่ควรเปลี่ยน Owner เป็น Optional เว้นแต่ Resource ออกแบบมาเช่นนั้นจริง
㉗ Error ตอนซื้อรถ
Flow อาจเป็น:
Character
↓
Identifier
↓
Purchase Vehicle
↓
Create Vehicle Row
↓
owner = NULL
↓
Error 1048
㉘ ต้องย้อนกลับไปหาเหตุผลว่า Owner หายตรงไหน
ไม่ใช่เพียง ALTER Table
㉙ Error plate cannot be null
Resource อาจ Generate Plate ไม่สำเร็จ
㉚ อย่าใช้ Plate ว่างเป็น Fix
Vehicle Systems หลายระบบใช้ Plate เพื่อ:
Garage
Keys
Ownership
การสร้างรถโดยไม่มี Plate ที่ Resource ต้องการอาจสร้างปัญหาต่อเนื่อง
㉛ Error phone_number cannot be null
อาจเกิดเมื่อ Phone System คาดว่าจะ Generate เบอร์ก่อนสร้าง Account
แต่ Generator ไม่คืนค่า
㉜ ต้องตรวจ Workflow ของ Phone Resource
บาง Script สร้างหมายเลข:
ตอนสร้าง Character
บาง Script:
ตอนเปิด Phone ครั้งแรก
อย่าปรับ Schema จาก Tutorial คนละ Resource
㉝ Error job cannot be null
Character Creation อาจไม่ได้ Assign Starter Job
㉞ Starter Job ต่างกันทุก Server ได้
เช่น Server หนึ่งอาจใช้:
unemployed
อีกระบบใช้ค่าอื่น
ต้องยึด Framework จริง
㉟ Error firstname cannot be null
Character Creator อาจส่ง Data ไม่ครบ
㊱ UI แสดงชื่อแล้วแต่ Database ยังได้ NULL ได้ไหม
ได้
เพราะ Data อาจหายระหว่าง:
NUI
↓
Client
↓
Server
↓
Database
㊲ ต้อง Debug ทุก Layer
อย่าเชื่อเพียงว่า UI มีข้อความอยู่
㊳ ตัวอย่าง Mapping ผิด
Client ส่ง:
firstName
Server อ่าน:
firstname
ถ้า Code/Languageแยกชื่อ Propertyเหล่านี้:
ค่าที่อ่านอาจไม่มี
㊴ Resource Update อาจเปลี่ยน Payload
เช่น Version ใหม่ส่ง:
character.firstname
แต่ Bridge เก่ายังอ่าน:
data.firstname
ผลคือ NULL
㊵ Error หลัง Update Resource
ตรวจ:
Changelog
Migration
Framework Bridge
Query Parameters
㊶ Error หลัง Update Framework
Resource เก่าอาจอ่าน Player Data จาก API ที่ Framework ใหม่เปลี่ยนไปแล้ว
㊷ Errorหลังเปลี่ยน ESX/QBCore
ยิ่งต้องตรวจ Adapter
ไม่ควรแก้ NOT NULL เพื่อให้ Script ที่ใช้ Framework ผิดทำงานต่อ
㊸ Framework Config ผิดเป็นต้นเหตุได้
เช่น:
Framework = "esx"
แต่ Server จริงใช้ระบบอื่น
㊹ Resource Auto-detect อาจต้องตรวจ
หากมีหลาย Core/Bridge Resources เปิดพร้อมกัน Configuration อาจไม่ตรงกับที่คิด
㊺ Errorหลังติดตั้ง Custom Script
Script อาจคาดว่า Player Object มี Field:
identifier
แต่ Frameworkจริงใช้ Mappingอื่น
㊻ ดู Documentation ของ Script
โดยเฉพาะ Requirements:
Framework Version
Database Resource
Required Dependency
㊼ Error 1048 กับ 1364 ต่างกันอย่างไร
นี่เป็นจุดที่มือใหม่สับสนบ่อย
Error 1364
ไม่ได้ส่ง Required Field และ Fieldไม่มี Default
Error 1048
ส่งค่าเข้า Fieldแล้ว แต่ค่าที่ส่งคือ NULL
MariaDBแยก Error 1048 (Column cannot be null) ออกจากกรณีไม่มี Defaultอย่างชัดเจน.
㊽ ตัวอย่าง 1364
Table:
owner NOT NULL ไม่มี DEFAULT
Query:
INSERT INTO vehicles (plate)
VALUES ('ABC123');
ไม่ได้อ้าง owner เลย
㊾ ตัวอย่าง 1048
Query:
INSERT INTO vehicles (owner, plate)
VALUES (NULL, 'ABC123');
ระบุ Owner แล้ว แต่ Value คือ NULL
㊿ ดังนั้นวิธี Debug ต่างกันเล็กน้อย
1364:
ทำไม Query ไม่ส่ง Field?
1048:
ทำไม Value ของ Field กลายเป็น NULL?
51. ตรวจ Query ก่อน
ตัวอย่าง:
INSERT INTO vehicles
(owner, plate, vehicle)
VALUES (?, ?, ?);
SQLดูปกติ
52. ต่อมาตรวจ Parameters
สมมติ:
owner = NULL
plate = ABC123
vehicle = {...}
Root Causeคือ owner
53. Parameter Order สำคัญ
Columns:
owner
plate
vehicle
แต่ Parameters:
plate
owner
vehicle
อาจทำค่าลงผิดตำแหน่ง
54. จำนวน Parameters เท่ากันไม่ได้แปลว่าถูก
ต้องเช็ก:
Count
Order
Values
55. Mapping ผิดอาจสร้าง Error อื่นด้วย
เช่น JSON ถูกส่งเข้า Plate
อาจเจอ:
Data Too Long
หรือ Type Problem
56. Errorหลายแบบหลัง Update
อาจเป็นสัญญาณว่า Parameter Mapping ทั้ง Query ผิด
57. ตรวจ Query ที่ Database เห็นจริง
Database Resource Logs ช่วยได้มาก
58. แต่ไม่ควรโพสต์ Parameters ทั้งหมด Public
เพราะอาจมี:
Player Identifiers
Private Data
59. Mask ข้อมูลก่อนขอความช่วยเหลือ
เก็บไว้เฉพาะ Context ที่จำเป็น
60. Query Parameter เป็น NULL ได้จาก Function Return
เช่น:
getIdentifier(player)
คืน:
nil
61. ต้องตรวจ Function ก่อน SQL
อย่าแก้ Databaseเพื่อชดเชย Function Bug
62. Characterยังโหลดอยู่แต่ Identifier Functionคืน NULLได้ไหม
ได้ถ้า Scriptใช้ Identifier Typeผิด
63. Identifier Types อาจแตกต่างกันตาม Resource
จึงต้องใช้ API/Identifier ที่ Resourceรองรับ
64. อย่าดึงข้อมูลจาก Player ID แบบเดา
Player Session IDกับ Persistent Identifierไม่ใช่สิ่งเดียวกัน
65. Error ownerหลัง Reconnect
อาจ Resource Cache Player Dataไม่พร้อมตอน Eventถูกเรียก
66. Race Condition เกี่ยวได้ไหม
ได้ในเชิง Application
เช่น Resourceเรียก Databaseก่อน Frameworkโหลด Character Dataเสร็จ
67. ตัวอย่าง
Player connected
↓
Resource event fires
↓
Player objectยังไม่พร้อม
↓
owner = nil
↓
INSERT
↓
1048
68. Fixไม่ใช่ Sleepแบบสุ่มเสมอไป
ควรรอ Event/Stateที่บอกว่า Player Dataพร้อมจริง
69. Hardcoded Delay เปราะบาง
เครื่อง/Serverช้าหรือเร็วต่างกัน
70. Event-driven Flow ดีกว่า
ถ้า Frameworkมี Eventสำหรับ:
Player Loaded
Character Selected
ควรใช้ตาม Documentation
71. Errorเฉพาะ Server Restart
Resource Startup Orderอาจเกี่ยว
72. Databaseเปิดแล้วแต่ Frameworkยังไม่พร้อม
Resourceบางตัวอาจเริ่ม Query Character/System Dataเร็วเกิน
73. Dependency Orderจึงสำคัญ
Resourceควรถูก Startตาม Dependenciesที่ผู้พัฒนากำหนด
74. Errorเฉพาะ Playerแรกหลัง Restart
ยิ่งควรสงสัย Startup/Initialization Race
75. Errorหลัง Restartแล้วหายเอง
อย่าปล่อยผ่าน
เพราะอาจเป็น Race Conditionที่เกิดไม่ทุกครั้ง
76. Errorแบบสุ่ม Debugยากกว่า
ควร Log:
Operation
Player state
Variableก่อน Query
77. อย่า Log Secret
เช่น:
Password
Token
78. Error 1048 ใน Inventory
เช่น:
owner cannot be null
ตอน Save Item
79. อาจเกิดเมื่อ Itemไม่มี Owner Mapping
เช่น Shared Storage/Drop Storageถูกส่งผ่าน Logicของ Personal Inventoryผิด
80. อย่า Default Ownerเป็น Playerคนแรก
เป็น Data Integrity Problemร้ายแรง
81. Shared Stashอาจใช้ Identifierคนละรูปแบบ
เช่น:
stash id
แทน Character Owner
ขึ้นกับ Inventory Resource
82. Resource Adapterต้องแยก Inventory Typesให้ถูก
83. Error 1048 ใน Housing
Property Ownership Recordอาจขาด:
owner
หรือ:
property_id
84. Property IDไม่ควร NULLถ้า Recordต้องอ้างบ้านหนึ่งหลัง
85. Errorใน Business
เช่น:
business_id
owner
หาย
86. Errorใน Banking
Account Recordอาจขาด:
account_owner
87. Account Ownerไม่ควร Defaultว่างเพียงเพื่อ Queryผ่าน
88. Errorใน Billing
Invoiceอาจขาด:
sender
receiver
ถ้า Columnถูกกำหนด Required
89. Errorใน Phone Messages
Messageอาจขาด:
sender
หรือ:
receiver
90. ตรวจ User Flow
Playerอาจส่งข้อความไป Contactที่ข้อมูลไม่ครบ
91. Errorเฉพาะ Recordเก่า
Legacy Dataอาจมี Field NULLอยู่แล้ว
92. แต่ Table NOT NULLรับ NULLเก่าได้อย่างไร
อาจเกิดจาก:
Schemaเพิ่งเปลี่ยน
Importจากระบบอื่น
Constraintถูกเพิ่มภายหลัง
93. Migrationจาก Nullable → NOT NULL
ต้อง Clean Existing NULLsก่อนหรือจัดการข้อมูลตาม Migration Plan
94. อย่า ALTER เป็น NOT NULLทันทีถ้ามี NULLอยู่
Migrationอาจ Failหรือทำให้ Applicationมีปัญหา
95. วิธีหาค่า NULL
เช่นแนวคิด:
SELECT *
FROM your_table
WHERE owner IS NULL;
MariaDBใช้ IS NULL เพื่อทดสอบว่าค่าเป็น NULL.
96. อย่าใช้ = NULL
โดยทั่วไปการตรวจ NULLควรใช้:
IS NULL
หรือ:
IS NOT NULL
MariaDBมี Operatorsเฉพาะสำหรับการตรวจ NULL.
97. ตัวอย่างตรวจค่าที่ไม่ NULL
SELECT *
FROM your_table
WHERE owner IS NOT NULL;
MariaDB IS NOT NULL จะคืน True เมื่อ Expressionไม่ใช่ NULL.
98. Existing NULLsต้องแก้อย่างไร
ต้องรู้ว่าค่า Owner/Identifierจริงควรเป็นอะไร
ไม่ควร Bulk Updateเป็นค่าปลอม
99. ถ้ากู้ค่าจาก Relationอื่นได้
อาจทำ Data Migration
แต่ต้อง Backupก่อน
100. ถ้ากู้ไม่ได้
อาจต้องตรวจ:
Logs
Ownership Records
Backups
ตาม Importanceของข้อมูล
101. อย่าทำ
UPDATE vehicles
SET owner = 'unknown'
WHERE owner IS NULL;
แบบสุ่ม
เพราะรถหลายคันจะมี Ownerเดียวกัน
102. การกำจัด NULLต้องรักษาความหมายข้อมูล
ไม่ใช่เพียงให้ Constraintผ่าน
103. Default Valueช่วย 1048ไหม
นี่เป็นจุดสำคัญ:
ถ้า Queryส่ง NULLมาโดยตรง การมี DEFAULTไม่ได้แปลว่าจะใช้ Defaultแทน NULLเสมอไป
การละ Columnกับการกำหนด NULLตรง ๆ เป็นคนละกรณีใน SQL.
104. ตัวอย่าง
Schema:
job NOT NULL DEFAULT 'unemployed'
Queryละ job:
Databaseสามารถใช้ Defaultตาม Definitionได้ในบริบทที่เหมาะสม.
105. แต่ Queryส่ง
job = NULL
ไม่ควรคิดว่า Defaultจะเข้ามาแทนโดยอัตโนมัติ
106. หากต้องการ Default
Applicationอาจ:
ละ Column
ใช้
DEFAULTตาม Syntax/Design
แทนส่ง NULLโดยไม่ตั้งใจ
107. แต่ Resourceทั่วไปควร Handleค่าใน Codeให้ชัด
อ่านง่ายกว่า
108. IFNULL() คืออะไร
MariaDBมี IFNULL(expr1, expr2) ซึ่งคืน expr1 หากไม่ NULL และคืนค่าทดแทนเมื่อ expr1เป็น NULL.
109. ใช้ IFNULLแก้ Errorได้ไหม
ใช้ได้ใน SQL Logicบางแบบ แต่ไม่ควรใช้เพื่อซ่อน Missing Identity Data
110. ตัวอย่างที่ไม่ควรทำ
owner NULL
↓
IFNULL(owner, 'unknown')
ถ้า Ownerต้องเป็น Characterจริง
111. IFNULLเหมาะกับ Display/Optional Logicมากกว่าในหลายกรณี
เช่นเลือก Labelสำรอง
แต่ต้องดู Data Modelจริง
112. COALESCEมีแนวคิดคล้ายกัน
แต่สำหรับ Error 1048 เป้าหมายหลักคือหาว่า NULLมาจากไหน
113. INSERT IGNOREช่วยไหม
MariaDBระบุว่า IGNORE สามารถเปลี่ยน Errorsบางประเภท รวมถึง Error 1048 ให้เป็น Warnings และปรับ Invalid Valuesให้เป็นค่าที่ใกล้เคียงซึ่งสามารถ Insertได้.
114. จึงไม่ควรใช้เป็น Fixทั่วไป
เพราะคุณอาจเปลี่ยนจาก:
เห็น Errorชัดเจน
เป็น:
บันทึกค่าที่ไม่ถูกต้องเงียบ ๆ
115. ตัวอย่างอันตราย
Owner NULLถูกเปลี่ยนเป็น Empty Value
Queryผ่าน
แต่ Vehicleไม่มี Ownerที่ถูกต้อง
116. Data Integrityเสียโดยไม่มี Errorแดง
อันตรายกว่าเดิม
117. Strict Handlingมีประโยชน์
Errorกำลังบอกว่าข้อมูล Requiredหายก่อน Databaseบันทึก Recordผิด
118. อย่าปิด Validationเพียงเพื่อให้ Consoleสะอาด
119. เปลี่ยน Columnเป็น NULLABLE ได้ไหม
ทาง Schemaทำได้ในหลายกรณีด้วย ALTER TABLE
แต่ต้องมีเหตุผลทาง Data Model
120. ตัวอย่าง Concept
เดิม:
discord_id VARCHAR(100) NOT NULL
ถ้า Discordเป็น Optionalจริงตาม Resource Design:
อาจควร Nullable
121. แต่ต้องตรวจ Applicationก่อน
Codeต้องรับมือ:
discord_id = NULL
ได้ด้วย
122. SQL Errorหายแต่ Scriptอาจพัง
หาก Codeทำ:
discord_id.length
โดยไม่ตรวจ NULL
123. Schema Changeต้องดูทั้งสองฝั่ง
Database + Application
124. Required Fieldควรคง NOT NULL
ถ้าการไม่มีค่าทำให้ Recordไม่มีความหมาย
125. Primary Keyและ NULL
MariaDBกำหนดว่า Primary Keyต้องมีส่วนประกอบที่เป็น NOT NULL และ Error 1171เกี่ยวข้องกับกรณี Primary Keyที่ Nullable.
126. ดังนั้นอย่าทำ Primary Identifier Nullableเพื่อแก้1048
นั่นขัดกับหน้าที่ของ Key
127. AUTO_INCREMENT มีพฤติกรรมพิเศษกับ NULL
MariaDBระบุว่า Numeric AUTO_INCREMENT Columnสามารถรับ NULLเพื่อให้ระบบสร้างค่า Auto Incrementถัดไป.
128. นี่เป็นข้อยกเว้นสำคัญ
ตัวอย่าง:
id AUTO_INCREMENT
กับ:
owner NOT NULL
ไม่ควรถูกคิดว่า NULLทำงานเหมือนกัน
129. Error id cannot be null
ถ้า IDควรเป็น AUTO_INCREMENTแต่ Errorเกิด:
ตรวจ Schemaว่า:
AUTO_INCREMENT
หายหรือไม่
130. อย่าตั้ง id = 0ทุก Row
อาจกลายเป็น Duplicate Primary Key
131. ตรวจ Official Schema
ถ้า Expected:
id AUTO_INCREMENT
แต่ Production:
id INT NOT NULL
นี่คือ Schema/Migration Problem
132. Errorหลัง Import SQLผิด Version
สามารถเกิดกรณีนี้ได้
133. Character Creation Errorหลัง Restore Backup
Codeใหม่อาจคาด Schemaใหม่
แต่ Backupนำ Structureเก่ากลับมา
134. ตรวจ Version Pair
Code Version + Database Schema Version
ต้องสอดคล้องกัน
135. Error 1048หลัง Migration
อาจ Migrationเปลี่ยน Columnเป็น NOT NULL
แต่ Codeยังส่ง NULL
136. Migrationอาจถูกต้องแต่ Code Deployไม่ครบ
เช่น Databaseถูกอัปเดตก่อน Resource
137. หรือ Codeใหม่แต่ Migrationไม่ครบ
ทั้งสองแบบสร้างปัญหาได้
138. Updateควรเป็นชุด
Resource Code
Config
Database Migration
139. Maintenance Windowช่วยลด Version Mismatch
โดยเฉพาะ Core Tables
140. Backupก่อน Migration
สำคัญเสมอ
141. Backupไม่ควรอยู่ Public
FiveM Databaseอาจมี:
Identifiers
Character Data
142. Errorหลังเพิ่ม Custom Column
สมมติเพิ่ม:
discord VARCHAR(100) NOT NULL
แต่ Character Creationไม่ได้ส่ง Discord
143. อาจเกิด 1364หรือ1048ตาม Query
ถ้า Queryละ Field:
1364ลักษณะหนึ่ง
ถ้า Queryใส่ Fieldแต่ส่ง NULL:
1048
144. ความแตกต่างนี้ช่วย Debug
อ่าน Queryจริง
145. Configสร้าง NULLได้
เช่น:
DefaultJob = nil
โดยไม่ได้ตั้งใจ
146. Environment Variableหายก็ได้
เช่น Resourceอ่าน Default Business IDจาก Environment แต่ Variableไม่ได้ถูกตั้ง
147. อย่าตั้ง Defaultค่าปลอมใน Production
แก้ Configuration Source
148. Errorเฉพาะ Server Production
Devอาจมี Configครบ แต่ Productionขาด
149. Errorเฉพาะ Dev
Production Configอาจถูก แต่ Local .envขาด
150. Environment Parityสำคัญ
Dev/Staging/Productionควรมี Required Configครบ
151. Errorเฉพาะ Characterหนึ่ง
Dataของ Characterนั้นอาจไม่มี Fieldที่ Resourceใหม่คาด
152. ตัวอย่าง Legacy Character
Characterสร้างก่อนเพิ่ม:
phone
Resourceใหม่คาด Phone Accountแล้วสร้าง Related Recordด้วย NULL
153. ต้องทำ Legacy Migration
ไม่ควร Delete Character
154. Migrationอาจ Generateค่าที่ขาด
ตาม Logicที่ Resourceรองรับ
155. Errorทุก Character
น่าสงสัย:
Code
Schema
Config
ระดับระบบ
156. Errorเฉพาะ Characterเก่า
น่าสงสัย Legacy Data
157. Errorเฉพาะ Characterใหม่
น่าสงสัย Creation Flow
158. Errorตอน Loginแต่ไม่ตอน Create
ตรวจ Sub-recordที่สร้างตอน Login
เช่น:
Phone Account
Settings
Statistics
159. Errorตอน Logout
ตรวจ Save/Log Recordที่ถูกสร้างตอน Disconnect
160. Errorตอนซื้อรถ
ตรวจ:
Character owner
plate
vehicle model data
161. Errorตอนเก็บรถ
อาจ Garage Resourceสร้าง History/State Recordโดยมี Field NULL
162. Errorตอน Impound
ตรวจ:
vehicle identifier
reason
officer
ตาม Schemaของ Resource
163. Errorตอน Banking
ตรวจ Transaction Fields:
sender
receiver
reference
164. Errorตอน Withdraw Cash
Resourceอาจ Log Transactionและ Required Columnหนึ่งหาย
165. Balance Updateอาจสำเร็จแต่ Log Insertล้มได้ไหม
ขึ้นกับ Transaction Designของ Resource
นี่คือเหตุผลที่ต้องตรวจ Gameplay Impactหลัง SQL Error
166. Errorตอน Billing
Invoice Creationอาจ Failทั้งหมด
167. Errorตอน Business Payroll
Employee Identifierหายอาจทำ Payment Recordผิด
168. Errorตอน Crafting
ถ้า Craft Log/Recipe Ownership Tableต้องมี Character Identifier
แต่ Resourceไม่ได้รับ Player Object
169. Errorตอน Job Reward
Reward Historyอาจต้อง Player ID
170. Errorตอน Whitelist
Identifier NULLแสดงว่าระบบไม่สามารถระบุ Accountที่กำลัง Whitelist
171. Errorตอน Ban
Ban Recordอาจต้อง:
target identifier
staff identifier
172. อย่า Default Targetเป็น Unknown
Moderation Dataจะใช้ไม่ได้
173. Errorใน Logsสำคัญ
แม้ Gameplayอาจยังทำงาน แต่ Staff Auditอาจหาย
174. Errorใน Core Saveสำคัญกว่า
หาก Character Dataไม่ได้ Saveควรแก้ก่อนเปิด Serverต่อเต็มรูปแบบ
175. Severityดูจาก Operation
ไม่ใช่ Error Numberอย่างเดียว
176. Queryหนึ่งล้มอาจ Rollbackไหม
ขึ้นกับ Transaction/Resource Design
อย่าคิดว่า Queryอื่นทั้งหมดทำหรือไม่ทำโดยอัตโนมัติ
177. หลัง Error Purchaseควร Verify
ตรวจ:
เงิน
Asset
Ownership
ว่า Stateสอดคล้องกัน
178. อย่ากด Purchaseซ้ำทันที
หาก Clientไม่รู้ว่าครั้งแรกสำเร็จบางส่วนหรือไม่
179. Duplicate Actionอาจสร้าง Errorต่อเนื่อง
เช่นหลังแก้ 1048แล้วเจอ 1062
เพราะ Recordบางส่วนถูกสร้างไปแล้ว
180. ตรวจ Databaseก่อน Retry Production Transaction
โดยเฉพาะ:
Vehicle
Property
Business
181. Error 1048กับ JSON
ถ้า JSON Fieldเป็น NOT NULL แต่ Resourceส่ง:
NULL
ต้องดูว่า Empty Stateควรเป็นอะไร
182. JSON Empty Object
{}
ไม่เหมือน NULL
183. JSON Empty Array
[]
ก็ไม่เหมือน NULL
184. Resourceอาจต้องการ Shapeเฉพาะ
อย่าเปลี่ยน NULLเป็น {}โดยอัตโนมัติ
185. Inventoryอาจต้อง Array
Metadataอาจต้อง Object
ขึ้นกับ Resource
186. Invalid Shapeอาจไม่ Error SQL
แต่ทำ Applicationพังภายหลัง
187. Errorหายไม่ได้แปลว่าข้อมูลถูก
นี่เป็นหลักที่ต้องจำ
188. Error position cannot be null
อย่าใส่:
0,0,0
แบบสุ่ม
เพราะ Characterอาจ Spawnผิดพื้นที่
189. ใช้ Starter Spawnตาม Resource Config
หาก Characterใหม่ต้องมี Position
190. Error model cannot be null
Character Appearance Resourceอาจไม่ได้ Set Player Modelก่อน Save
191. อย่า Defaultเป็น Modelสุ่ม
ใช้ Character Creator Logicที่ถูกต้อง
192. Error vehicle cannot be null
Garage Tableอาจต้อง Vehicle Properties JSON
ถ้า Serializationล้มเหลว:
Parameterกลายเป็น NULL
193. ตรวจ JSON Encodeก่อน Query
ถ้า Encode Functionคืน nil/null:
Root Causeอาจอยู่ Data Structure
194. Circular Data Structureอาจทำ Serializationล้มได้
ใน Custom Codeบางประเภท
แต่ควรดู Errorของ Encoderก่อน
195. อย่าจับ Serialization Errorแล้วส่ง NULLต่อ
ควร Stop Operationและ Logสาเหตุ
196. Fail Fast คืออะไร
เมื่อ Required Dataไม่ครบ:
หยุดก่อน Database
ดีกว่าปล่อย NULLเข้า Query
197. Example Validation
แนวคิด:
if owner is missing:
return error
ก่อน:
INSERT vehicle
198. User-facing Errorควรชัด
แทนปล่อย Playerคิดว่าซื้อรถสำเร็จ
Resourceอาจแจ้ง:
Transaction failed
Try again/contact staff
ตาม Design
199. แต่ไม่ควรแสดง SQL Errorดิบให้ Playerทั่วไป
Database Structureเป็น Technical Detail
200. Server Consoleเก็บ Technical Contextแทน
201. Error Handlingที่ดีประกอบด้วย
Validate
Log
Stop unsafe operation
Return controlled failure
202. Query Parameter Loggingใน Production
ควรจำกัดข้อมูล Sensitive
203. Error 1048 หลังเปลี่ยน Database Library
เช่น Resourceถูก Convertไปใช้ Wrapperใหม่
Parameter APIอาจต่างกัน
204. Parameterชื่อไม่ตรง
เช่น Libraryเก่าใช้ Named Parametersแบบหนึ่ง
Libraryใหม่คาดอีกแบบ
Valueอาจไม่ได้ Bind
205. Generated Queryจึงสำคัญ
ตรวจสิ่งที่ Databaseได้รับจริง
206. อย่าแค่เปลี่ยน Export Name
Database Wrapper Migrationอาจต้องแก้:
Query API
Parameter Format
Return Values
207. Errorหลัง oxmysql Conversion
ตรวจ Official Conversion Guideของ Versionที่ใช้
ไม่ควรสมมติ APIจาก Resourceเก่า
208. Error Stackขึ้นชื่อ Database Wrapper
ไม่ได้หมายความว่า Wrapperเป็นต้นเหตุ
Caller Resourceอาจส่ง NULLมาเอง
209. หา Resource Caller
ดู Stack Trace/Console Prefix
210. Searchชื่อ Columnใน Source
เช่น Error:
Column 'owner' cannot be null
ค้น:
owner
ใน Resourceนั้น
211. Search INSERT/UPDATE
หา Queryที่เขียน Fieldดังกล่าว
212. Search Functionที่สร้าง Parameter
เช่น:
getOwnerIdentifier()
213. Debugเป็น Chain
DB Error
↓
Query
↓
Parameter
↓
Variable
↓
Function
↓
Source Data
214. นี่เป็นวิธีเร็วที่สุด
แทนแก้ Databaseทุกครั้ง
215. ตรวจ Schemaด้วย
เพราะบางครั้ง NULLเป็น Stateที่ควรอนุญาตจริง แต่ Production Tableถูกสร้างผิด
216. ตัวอย่าง Optional Field
สมมติ:
secondary_phone
ควร Optional
Official Schemaเป็น:
NULL
แต่ Productionถูกแก้เป็น:
NOT NULL
ในกรณีนี้ Schemaอาจเป็นต้นเหตุ
217. Compareกับ Official Schema
ก่อน ALTER
218. ใช้ SHOW CREATE TABLE
SHOW CREATE TABLE your_table;
เพื่อดู Definitionจริง
219. ใช้ DESCRIBE
DESCRIBE your_table;
เพื่อดู:
Null
Default
Type
220. ถ้า Official Schemaกับ Productionต่าง
ใช้ Migrationที่ถูกต้องแทน Manual Guessเมื่อมี
221. ALTER TABLE เปลี่ยน Nullabilityได้
แต่เป็นการเปลี่ยน Data Contractของ Table จึงควรทำหลัง Backupและตรวจ Resourceทั้งหมดที่ใช้ Fieldนั้น
222. อย่าใช้ ALTERจากบทความตรง Productionทันที
ชื่อ Table/Fieldและ Requirementแต่ละ Serverไม่เหมือนกัน
223. Backupก่อน ALTER
โดยเฉพาะ Core Player Tables
224. Maintenance Window
เหมาะกับ Schema Changesสำคัญ
225. Testหลัง ALTER
Trigger Featureเดิมที่เคย Error
ไม่ใช่แค่ Restart Server
226. ตรวจ Rowที่สร้างใหม่
เช็กว่า Fieldมีค่าที่มีความหมาย
227. ถ้า Fieldกลายเป็น NULLได้แล้ว
ต้องทดสอบว่า Resourceอ่าน NULLได้
228. Example Phone UI
ถ้า:
phone_number = NULL
Phone UIควร Handle “ยังไม่มีหมายเลข”
หาก Designนั้นรองรับ
229. ถ้าไม่รองรับ
เปลี่ยน Schemaเป็น Nullableไม่ใช่ Fixที่ถูก
230. Error 1048หลัง Database Merge
Source Databaseหนึ่งอาจมี NULLใน Fieldที่ Destinationกำหนด NOT NULL
231. Mergeต้อง Data Mapping
กำหนดว่า:
NULLเก่า
ควรเป็นค่าอะไร
ตาม Business Logic
232. อย่า Bulk Replace NULLด้วยค่าเดียว
สำหรับ Unique/Identity Fields
233. Duplicate Errorอาจตามมา
ถ้าใส่ Defaultเดียวกันให้ทุก Rowและ Fieldมี Unique Constraint
234. Error Chainตัวอย่าง
1048
→ เปลี่ยน NULLเป็น UNKNOWN
→ Multiple Rowsใช้ UNKNOWN
→ 1062 Duplicate Entry
235. แก้ Root Causeตั้งแต่แรกดีกว่า
236. Error 1048หลัง Data Import
ตรวจว่า Exportมี NULL Valuesจริงหรือไม่
237. Source Schemaอาจอนุญาต NULL
แต่ Destinationห้าม
238. ต้อง Normalize Schema/Dataก่อน Import
239. CSV Importก็เกิดได้
ช่องว่างใน CSVอาจถูก Interpretแตกต่างตาม Import Tool/Options
240. อย่าคิดว่า Blank Cell = NULLเสมอไป
ต้องดู Import Settings
241. Data-only Backupต้องระวัง
Destination Schemaอาจเปลี่ยน Nullabilityหลัง Backupถูกสร้าง
242. Full Backupอาจ Restore Schemaเก่าด้วย
จึงต้องรู้ว่าต้องการ:
Restore Data
Restore Schema
ทั้งคู่
243. Resource Updateแล้ว Restore Backupเก่า
อาจย้อน Schemaโดยไม่ตั้งใจ
244. Error 1048หลัง Database Migration
ตรวจ Migration Order
บาง Stepอาจต้อง Backfillก่อนเพิ่ม NOT NULL
245. Migrationที่แข็งแรงควรจัดการ Existing NULLs
ก่อนบังคับ Constraintใหม่
246. แต่ถ้าเป็น Third-party Resource
ให้ใช้ Migrationของ Developer
ไม่เขียนเองหากไม่จำเป็น
247. Custom Developerควรเขียน Migrationอย่างระวัง
ตัวอย่าง Concept:
เพิ่ม Columnแบบ Optional
Fillข้อมูล
ตรวจไม่มี NULL
เปลี่ยนเป็น NOT NULL
เมื่อตรงกับ Business Requirement
248. ไม่ใช่ทุก Migrationต้องใช้ Patternนี้
ขึ้นกับ Data Model
249. Database Constraintมีประโยชน์
NOT NULLช่วยป้องกัน Recordที่ขาดข้อมูลสำคัญจากถูกบันทึก
250. อย่ามอง Constraintเป็นศัตรู
Errorอาจกำลังช่วยป้องกันข้อมูลเสีย
251. Error 1048กับ Primary Key
MariaDBกำหนดให้ส่วนต่าง ๆ ของ Primary Keyต้องเป็น NOT NULL.
252. อย่าเอา NULLเข้า Primary Identifier
ถ้าค่าไม่พร้อม:
อย่าสร้าง Record
253. AUTO_INCREMENTเป็นกรณีพิเศษ
Numeric Auto Incrementสามารถใช้ NULLเป็นสัญญาณให้สร้างค่าถัดไปตาม MariaDB behavior.
254. อย่าใช้ข้อยกเว้นนี้กับทุก Field
เฉพาะ Columnที่กำหนด AUTO_INCREMENTตาม Schema
255. Error 1048 FAQ
FiveM Column cannot be null คืออะไร
MariaDBได้รับ NULLสำหรับ Columnที่ไม่อนุญาต NULL และคืน Error 1048 / SQLSTATE 23000 / ER_BAD_NULL_ERROR.
Error 1048 กับ 1364 เหมือนกันไหม
ไม่เหมือนกัน 1048เน้นกรณีค่าที่ถูกส่งเป็น NULL ส่วน 1364เกี่ยวกับ Fieldที่ไม่มี Defaultเมื่อถูกละออกจาก Statementในบริบทที่เกี่ยวข้อง.
NULL กับ Empty Stringเหมือนกันไหม
ไม่เหมือนกัน NULLหมายถึงไม่มีค่า ส่วน ''เป็น Stringที่มีความยาวศูนย์
เปลี่ยน NULL เป็น '' ได้ไหม
เฉพาะเมื่อ Empty Stringเป็นค่าที่ถูกต้องตาม Resourceจริง ไม่ควรใช้กับ Identifier/Ownerเพียงเพื่อให้ Errorหาย
เปลี่ยน Columnเป็น Nullableได้ไหม
ได้ทาง Schemaในกรณีที่ Fieldนั้น Optionalจริงและ Applicationรองรับ NULL แต่ไม่ควรทำแบบทั่วไป
identifier cannot be null แก้อย่างไร
ตรวจ Identifier Retrieval, Framework Bridge และ Character INSERT ไม่ควรแก้ด้วยการทำ Identifier Optional
citizenid cannot be null แก้อย่างไร
ตรวจ Character ID Generatorและ Mappingก่อน Query
owner cannot be null แก้อย่างไร
ตรวจว่า Resourceได้รับ Character Identifier/Ownerก่อนสร้าง Vehicle, PropertyหรือAssetหรือไม่
plate cannot be null แก้อย่างไร
ตรวจ Vehicle Plate Generatorและ Query Parameters
phone_number cannot be null แก้อย่างไร
ตรวจ Phone Number Generation Flowและ Schemaของ Phone Resourceที่ใช้จริง
job cannot be null แก้อย่างไร
ตรวจ Character Starter Job Logic และ Framework Schema
id cannot be null แก้อย่างไร
ถ้า IDควรเป็น AUTO_INCREMENT ให้ตรวจ Schema เพราะ MariaDBมี behaviorพิเศษสำหรับ NULLบน Numeric AUTO_INCREMENT Columns.
Default Valueช่วยไหม
ช่วยเมื่อ Designต้องการ Defaultและ Statementใช้ Defaultตาม SQL behavior แต่การส่ง NULLโดยตรงไม่ควรถูกเหมารวมกับการละ Column.
ใช้ IFNULLได้ไหม
MariaDBมี IFNULL()เพื่อคืนค่าทดแทนเมื่อ Expressionเป็น NULL แต่ไม่ควรใช้เพื่อซ่อน Missing Identity/Ownership Data.
ใช้ INSERT IGNOREได้ไหม
ไม่แนะนำเป็น Fixทั่วไป เพราะ MariaDBสามารถเปลี่ยน Errorรวมถึง 1048เป็น Warningและ Insertค่าที่ถูกปรับแทน ซึ่งอาจซ่อนข้อมูลผิด.
Clear FiveM Cacheช่วยไหม
โดยทั่วไปไม่ใช่ Fixสำหรับ Server-side Database NULL Error
Restart MariaDBช่วยไหม
ไม่ ถ้า Resourceยังส่ง NULLเดิม
Restart FiveMช่วยไหม
หลังแก้ Codeอาจต้อง Reload Resource แต่ Restartอย่างเดียวไม่แก้ NULL Source
ต้องลบ Databaseไหม
ไม่
Error1048ส่วนใหญ่ควรแก้ที่:
Resource Logic
Data Mapping
Configuration
Schema Compatibility
Errorเกิดหลัง Update Resourceทำอย่างไร
ตรวจ:
Resource Version
Migration
Framework Adapter
Query Parameters
Errorเกิดหลัง Framework Updateทำอย่างไร
ตรวจว่า Resourcesที่อ่าน Player Objectยังรองรับ Framework API/Schemaใหม่หรือไม่
Errorเกิดเฉพาะ Characterเก่า
ตรวจ Legacy Dataและ Migration
Errorเกิดเฉพาะ Characterใหม่
ตรวจ Character Creation Flow
Errorเกิดทุกคน
ตรวจ Config/Code/Schemaระดับระบบ
Errorเกิดบางครั้ง
ตรวจ Timing, Race Condition และ Variableที่บางครั้งยังไม่พร้อมก่อน Query
Errorตอนซื้อรถ
ตรวจ Ownerและ Plateก่อน Insert Vehicle
Errorตอนสร้างบ้าน
ตรวจ Owner/Property Identifier
Errorตอนสร้าง Business
ตรวจ Owner/Internal Business ID
Errorตอนส่ง Invoice
ตรวจ Sender/Receiverและ Fieldsที่ Required
Errorตอน Save Inventory
ตรวจ Owner/Stash Identifierและ Serialized Data
Errorหลัง Restore Backup
ตรวจว่า Backup Schemaกับ Code Versionปัจจุบันตรงกันหรือไม่
Errorหลัง Import Data
ตรวจว่า Sourceมี NULLใน Columnที่ Destinationกำหนด NOT NULLหรือไม่
ต้อง Backupก่อน ALTERไหม
ควรอย่างยิ่ง โดยเฉพาะ Production/Core Tables
สรุป FiveM MySQL Column Cannot Be Null Error 1048
FiveM MySQL/MariaDB Error 1048 Column cannot be null เกิดเมื่อ Resource ส่งค่า NULL เข้า Column ที่ Database ไม่อนุญาตให้เป็น NULL โดย MariaDB ระบุ Error นี้เป็น ER_BAD_NULL_ERROR และ SQLSTATE 23000.
วิธีวิเคราะห์ที่ควรจำคือ:
Error 1048
↓
Column ไหน?
↓
Query ไหน?
↓
Parameter ไหนเป็น NULL?
↓
NULL เกิดจาก Function / Config / Player Data / Migration?
↓
Schema ควร NOT NULL จริงไหม?
↓
แก้ที่ต้นเหตุ
สิ่งที่ comsiam แนะนำคืออย่าเริ่มด้วยการเปลี่ยน NOT NULL เป็น NULL หรือเปลี่ยน NULL เป็น Empty Stringทุกจุด เพราะ Fieldsอย่าง Character ID, Vehicle Owner, Plate, Account Owner หรือ Business ID อาจจำเป็นต่อ Data Integrity การปล่อยให้ค่าพวกนี้ว่างสามารถทำให้ระบบดูเหมือนกลับมาใช้ได้ แต่สร้างข้อมูลที่ไม่สามารถเชื่อมกับเจ้าของจริงได้ภายหลัง
อีกหลักที่ comsiam แนะนำคือให้แยก Error 1048 กับ Error 1364 ให้ชัด: 1364 ให้ถามว่า “ทำไม INSERT ไม่ได้ส่ง Field นี้?” ส่วน 1048 ให้ถามว่า “ทำไม Resource ส่ง Field นี้มาเป็น NULL?” จากนั้นตรวจ Query Parameters, Framework Bridge, Resource Version และ Schemaจริงก่อนใช้ ALTER TABLE หรือ Migration และควร Backup Production Databaseก่อนเปลี่ยนโครงสร้างข้อมูลทุกครั้ง
Comments
Post a Comment