So, I've finally made some mods using SQL, and I must say, it certainly has its advantages. After learning the workflow the work gets far faster than XML, and it's easier to spot errors in syntax as the syntax is more forgiving.
That being said, I see many people with fear of moving from XML to SQL (I'm looking at you Viregel). I understand because its odd to change something you've already been doing for a while to something that seems very different; however, the truth is that XML and SQL are not at all that different, and that SQL certainly has its advantages over XML.
So, this little tutorial is going to help you guys move from XML to SQL if you're willing (or else
) ... Before starting, I must say I learned SQL for Civ5, so I'm nowhere near a master of sql or anything. All that will be said will be related to Civ5 Modding by itself.
1. What's with all the Caps!
Time to look at the first glance differences between XML and SQL... For this, we'll have a simple example of each.
XML (or, what you're accustomed of):
SQL (or, what you're afraid of):
Scary, huh? Well, both codes do exactly the same thing (Making the Peleset be the UU of the Philistines).
The first diference you'll notice is that the SQL thing doesn't have <GameData>, <Row> or brackets for that matter. The second thing you'll notice are the scary caps at INSERT INTO, and VALUES...
The way Civ works, you're adding "Rows" into database tables, by using the Row thing. To make sure you're adding Rows in the right table, you must also say <Civilization_UnitClassOverrides> and <GameData>... That's what you've been doing for a while by now, most likely
SQL is far more direct. Instead of nesting stuff vertically it simply needs INSERT INTO 'table name' to know you're adding whatever you want to the right table. That's simply it, Insert into means, add this into that table (in this case, Civilization_UnitClassOverrides)... What you usually put under "Row" is what goes on the VALUES part, you're saying what you want to insert into the specified table.
Now, now, some of you probably have this:
face... Well, let's look at our codes again, but instead of looking at the scary differences, let's look at the nice similarities
(with colours!)
XML :
SQL:
As you can see, there are more similarities than differences! Yay! So, the difference is just the layout, the syntax. The logic you've been using for now still works, you just put things in a different (and faster) way. Don't Panic!
2. Basic SQL syntax
So, now let's just look at a fake SQL code:
What you're doing is assigning 'A' into Tag_A, 'B' into Tag_B, and '24' into Tag_C... if you want to see it in XML, it would be something like this:
In SQL, the code is actually a bit shorter. You don't have to open and close the Table name or Rows... Its not needed at all!, you only have to put the tag names once and done. Now, it does require some few things to work, or else.
After saying INSERT INTO Table_A you must write all tags you want to change/add between these (----), and to sepparate each you just use some comas ',' (except for the last one, as there's nothing left afterwards).
Like this: INSERT INTO Table_A (Tag_A, Tag_B, Tag_C) ... As you can see, it doesn't matter if they are on the same row in the text, you can press enter once, twice, or more, depending what looks better for you. You can also add spaces between Table_A and (...) as much as you want, so you can give it the shape you wish (in XML a space or an enter is going to kill the whole document).
After saying "INSERT INTO Table_A (Tag_A, Tag_B, Tag_C) you need to say what VALUES you want to give to each of your tags. Now, there's something important here, text values (like UNIT_MUSKETMAN) must go between these ''. Number values need nothing in particular (because they are numbers and not text)... and finally boolean (true/false) become numbers (1/0 respectively)... Also at the end of VALUES you must put a semicolon ";" to end the thing properly... So like this:
If it is UNIT_MUSKETMAN it goes like 'UNIT_MUSKETMAN' (notice the fancy quotes)
If it is 100, it goes like 100 (no quotes)
If it is true, it goes 1
if it is false, it goes 0
Like this: VALUES ('A', 'B', 24)... Again, spaces and enters don't matter much.
These three codes work even if they have different spaces and enters:
So, the thing with SQL is that you can move around things so they fit with each other nicely
(using Tab, for example)
This way, it's very hard to get lost, and you know fastly what value corresponds to what tag.
3. But, Civ5 files are all in XML, how will I know what tag to use?
Don't worry! It might seem easier just to copy a tag like <CultureFromKills>100</CultureFromKills> for your trait in XML... but in SQL it isn't that different at all... Case in question:
We have a Trait for our Civ, to put it in XML we do something like this:
To do the same in SQL we do this:
Now, let's say we want to give this Generic trait the same Culture from Kills as the Aztecs. By searching the game's files we know that <CultureFromKills>100</CultureFromKills> does it... In XML we simply copy it, right?
Easy! Well, in SQL it isn't that hard either:
Might not be as straightforward as copy-pasting it, but you're still simply adding the Tag at the end of the line and then putting the 100 there too. It's still very easy and it's easier too look at, if you comitted a mistake it will be fairly easy to see where it was (specially in long civ tables, like Units or Buildings)
4. Advantages of SQL
So... now that you know your basics, let's see what's easier on SQL than it is on XML. We'll go little by little.
4.1. Easy Comments!
Comments are things you can put on code that are not going to be executed, they are useful as you can point out things of your code, or also useful to temporabily disable some part of it.
Comments in XML are like this: <!-- Comment --> ... As you can see you need to open and close (pretty much like everything in XML), using this <!-- to open and this --> to close... Simple, but it can get annoying. CivBE also has an issue with putting enters between such comment brackets.
For comments in SQL you just need this: --Comment . Two single characters and you have commented all the line!
Now, this may not seem as useful, but it really is. To disable a whole <Row> in XML you must put the brackets at the beginning and at the end, being careful with closing incorrectly everything... To disable our trait in SQL we just need to do this:
Simply putting two characters! ... Anyway, another fancy use is what JFD does with comments, which certainly helps in putting everything in order. Because it is a comment, you can put anything you want on the line after the two -- thingies. So, you can put some decoration like this:
Very nice, and keeps things easier to look at.
4.2. Stealing from other tables
Another thing that is a lot easier in SQL than in XML is stealing data from other tables. Say you want to add a Building, but since it's a Temple replacement you want it to be a Temple just with no mantenaince cost (let's imagine you also want the icon and the text and description, because it's a dummy UB)... In XML you'd have to copy the whole BUILDING_TEMPLE table with all its values... in SQL you need somethign like this:
Now, there are some new things here, of course. We'll explain them now... the first line is easy, it's just a INSERT INTO thing, like you've seen before.
The next line is odd, instead of VALUES it has a SELECT... and the things after select are not between ()... This means you're going to "select" some of the values from another existing Building type (the Temple)... That's why everything is just the same BUT the building type (because its another building, BUILDING_DUMMY_TEMPLE) and the GoldManteinance (which is now 0)...
Then it says FROM Buildings WHERE (Type = 'BUILDING_TEMPLE')... This means, Insert these stuff by selecting the valuse from the "Buildings" table, where the type of the building is BUILDING_TEMPLE... this is how it selects the right values
... With practice, it becomes far easier and faster using this to create UB and UU, as you'll even have your own templates (or you will have stolen some from JFD
)
4.3. Easier mistake checking
In XML you commit one mistake in one file, and the whole file ruins itself.. You suddenly have a whole civ not working and you don't even know why.
In SQL, every single mistake is individual. So, if you only got your mistake in setting the UnitClassOverrides, the civ will exist, just without a UU (so you'll know faster where the mistake was at)... or if you got the issue at the Buildings yield,your building will exist, but without the yield. Is a lot easier and more relaxing
4.4. Putting together a lot of Rows
Another advantage is putting together a lot of rows... Let's see how you use XML to put spies to your civ:
A long and boring code. Now let's see it in SQL:
You no longer need to scroll down that much, and you don't need that many <Row>s everywhere. Now, as you can see, to separate each line you just need a comma ( , ) instead of a semicolon ( ; ) which only goes in the last one.
For another example, I'll just show you this:
This adds all Building Classes I needed in Haiti, in just a few easy to look lines
4.5. More Advanced Advantages and Resources
This tutorial ends here, but if you're willing there are some more advanced techniques to use in SQL. Some links if you're interested:
The End
Enjoy as you are assimilated to the one true master code
(XML is still useful for changing/adding the Pedia texts and descriptions btw)
For any questions, blasphemies or whatever, just post them.
That being said, I see many people with fear of moving from XML to SQL (I'm looking at you Viregel). I understand because its odd to change something you've already been doing for a while to something that seems very different; however, the truth is that XML and SQL are not at all that different, and that SQL certainly has its advantages over XML.
So, this little tutorial is going to help you guys move from XML to SQL if you're willing (or else

1. What's with all the Caps!

Time to look at the first glance differences between XML and SQL... For this, we'll have a simple example of each.
XML (or, what you're accustomed of):
Code:
<GameData>
<Civilization_UnitClassOverrides>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<UnitClassType>UNITCLASS_SPEARMAN</UnitClassType>
<UnitType>UNIT_PHILISTINE_PELESET</UnitType>
</Row>
</Civilization_UnitClassOverrides>
</GameData>
SQL (or, what you're afraid of):
Code:
INSERT INTO Civilization_UnitClassOverrides
(CivilizationType, UnitClassType, UnitType)
VALUES ('CIVILIZATION_LEUGI_PHILISTINE', 'UNITCLASS_SPEARMAN', 'UNIT_PHILISTINE_PELESET');
Scary, huh? Well, both codes do exactly the same thing (Making the Peleset be the UU of the Philistines).
The first diference you'll notice is that the SQL thing doesn't have <GameData>, <Row> or brackets for that matter. The second thing you'll notice are the scary caps at INSERT INTO, and VALUES...
The way Civ works, you're adding "Rows" into database tables, by using the Row thing. To make sure you're adding Rows in the right table, you must also say <Civilization_UnitClassOverrides> and <GameData>... That's what you've been doing for a while by now, most likely

SQL is far more direct. Instead of nesting stuff vertically it simply needs INSERT INTO 'table name' to know you're adding whatever you want to the right table. That's simply it, Insert into means, add this into that table (in this case, Civilization_UnitClassOverrides)... What you usually put under "Row" is what goes on the VALUES part, you're saying what you want to insert into the specified table.
Now, now, some of you probably have this:


XML :
Code:
<GameData>
<[COLOR="Red"]Civilization_UnitClassOverrides[/COLOR]>
<Row>
<[COLOR="Blue"]CivilizationType[/COLOR]>[COLOR="Navy"]CIVILIZATION_LEUGI_PHILISTINE[/COLOR]</[COLOR="Blue"]CivilizationType[/COLOR]>
<[COLOR="YellowGreen"]UnitClassType[/COLOR]>[COLOR="SandyBrown"]UNITCLASS_SPEARMAN[/COLOR]</[COLOR="YellowGreen"]UnitClassType[/COLOR]>
<[COLOR="Lime"]UnitType[/COLOR]>[COLOR="SeaGreen"]UNIT_PHILISTINE_PELESET[/COLOR]</[COLOR="Lime"]UnitType[/COLOR]>
</Row>
</[COLOR="Red"]Civilization_UnitClassOverrides[/COLOR]>
</GameData>
SQL:
Code:
INSERT INTO [COLOR="Red"]Civilization_UnitClassOverrides[/COLOR]
([COLOR="Blue"]CivilizationType[/COLOR], [COLOR="YellowGreen"]UnitClassType[/COLOR], [COLOR="Lime"]UnitType[/COLOR])
VALUES ('[COLOR="Navy"]CIVILIZATION_LEUGI_PHILISTINE[/COLOR]', '[COLOR="SandyBrown"]UNITCLASS_SPEARMAN[/COLOR]', '[COLOR="SeaGreen"]UNIT_PHILISTINE_PELESET[/COLOR]');
As you can see, there are more similarities than differences! Yay! So, the difference is just the layout, the syntax. The logic you've been using for now still works, you just put things in a different (and faster) way. Don't Panic!
2. Basic SQL syntax

So, now let's just look at a fake SQL code:
Code:
INSERT INTO Table_A
(Tag_A, Tag_B, Tag_C)
VALUES ('A', 'B', 24);
What you're doing is assigning 'A' into Tag_A, 'B' into Tag_B, and '24' into Tag_C... if you want to see it in XML, it would be something like this:
Code:
<GameData>
<Table_A>
<Row>
<Tag_A>A</Tag_A>
<Tag_B>B</Tag_B>
<Tag_C>24</Tag_C>
</Row>
</Table_A>
</GameData>
In SQL, the code is actually a bit shorter. You don't have to open and close the Table name or Rows... Its not needed at all!, you only have to put the tag names once and done. Now, it does require some few things to work, or else.
After saying INSERT INTO Table_A you must write all tags you want to change/add between these (----), and to sepparate each you just use some comas ',' (except for the last one, as there's nothing left afterwards).
Like this: INSERT INTO Table_A (Tag_A, Tag_B, Tag_C) ... As you can see, it doesn't matter if they are on the same row in the text, you can press enter once, twice, or more, depending what looks better for you. You can also add spaces between Table_A and (...) as much as you want, so you can give it the shape you wish (in XML a space or an enter is going to kill the whole document).
After saying "INSERT INTO Table_A (Tag_A, Tag_B, Tag_C) you need to say what VALUES you want to give to each of your tags. Now, there's something important here, text values (like UNIT_MUSKETMAN) must go between these ''. Number values need nothing in particular (because they are numbers and not text)... and finally boolean (true/false) become numbers (1/0 respectively)... Also at the end of VALUES you must put a semicolon ";" to end the thing properly... So like this:
If it is UNIT_MUSKETMAN it goes like 'UNIT_MUSKETMAN' (notice the fancy quotes)
If it is 100, it goes like 100 (no quotes)
If it is true, it goes 1
if it is false, it goes 0
Like this: VALUES ('A', 'B', 24)... Again, spaces and enters don't matter much.
These three codes work even if they have different spaces and enters:
Code:
INSERT INTO Table_A
(Tag_A, Tag_B, Tag_C)
VALUES ('A', 'B', 'C');
INSERT INTO Table_A (Tag_A, Tag_B, Tag_C)
VALUES ('A', 'B', 'C');
INSERT INTO Table_A (Tag_A, Tag_B, Tag_C)
VALUES ('A','B','C');
So, the thing with SQL is that you can move around things so they fit with each other nicely

Code:
INSERT INTO Table_A (Tag_A, Tag_B, Tag_C)
VALUES ('A', 'B', 'C');
This way, it's very hard to get lost, and you know fastly what value corresponds to what tag.

3. But, Civ5 files are all in XML, how will I know what tag to use?

Don't worry! It might seem easier just to copy a tag like <CultureFromKills>100</CultureFromKills> for your trait in XML... but in SQL it isn't that different at all... Case in question:
We have a Trait for our Civ, to put it in XML we do something like this:
Spoiler :
Code:
<GameData>
<Traits>
<Row>
<Type>TRAIT_GENERIC</Type>
<Description>TXT_KEY_TRAIT_GENERIC</Description>
<ShortDescription>TXT_KEY_TRAIT_GENERIC_SHORT</ShortDescription>
</Row>
</Traits>
</GameData>
To do the same in SQL we do this:
Code:
INSERT INTO Traits
(Type, Description, ShortDescription)
VALUES ('TRAIT_GENERIC', 'TXT_KEY_TRAIT_GENERIC', 'TXT_KEY_TRAIT_GENERIC_SHORT');
Now, let's say we want to give this Generic trait the same Culture from Kills as the Aztecs. By searching the game's files we know that <CultureFromKills>100</CultureFromKills> does it... In XML we simply copy it, right?
Spoiler :
Code:
<GameData>
<Traits>
<Row>
<Type>TRAIT_GENERIC</Type>
<Description>TXT_KEY_TRAIT_GENERIC</Description>
<ShortDescription>TXT_KEY_TRAIT_GENERIC_SHORT</ShortDescription>
<CultureFromKills>100</CultureFromKills>
</Row>
</Traits>
</GameData>
Easy! Well, in SQL it isn't that hard either:
Code:
INSERT INTO Traits
(Type, Description, ShortDescription, CultureFromKills)
VALUES ('TRAIT_GENERIC', 'TXT_KEY_TRAIT_GENERIC', 'TXT_KEY_TRAIT_GENERIC_SHORT', 100);
Might not be as straightforward as copy-pasting it, but you're still simply adding the Tag at the end of the line and then putting the 100 there too. It's still very easy and it's easier too look at, if you comitted a mistake it will be fairly easy to see where it was (specially in long civ tables, like Units or Buildings)
4. Advantages of SQL

So... now that you know your basics, let's see what's easier on SQL than it is on XML. We'll go little by little.
4.1. Easy Comments!
Comments are things you can put on code that are not going to be executed, they are useful as you can point out things of your code, or also useful to temporabily disable some part of it.
Comments in XML are like this: <!-- Comment --> ... As you can see you need to open and close (pretty much like everything in XML), using this <!-- to open and this --> to close... Simple, but it can get annoying. CivBE also has an issue with putting enters between such comment brackets.
For comments in SQL you just need this: --Comment . Two single characters and you have commented all the line!

Now, this may not seem as useful, but it really is. To disable a whole <Row> in XML you must put the brackets at the beginning and at the end, being careful with closing incorrectly everything... To disable our trait in SQL we just need to do this:
Code:
[COLOR="SeaGreen"]--INSERT INTO Traits
-- (Type, Description, ShortDescription, CultureFromKills)
--VALUES ('TRAIT_GENERIC', 'TXT_KEY_TRAIT_GENERIC', 'TXT_KEY_TRAIT_GENERIC_SHORT', 100);[/COLOR]
Simply putting two characters! ... Anyway, another fancy use is what JFD does with comments, which certainly helps in putting everything in order. Because it is a comment, you can put anything you want on the line after the two -- thingies. So, you can put some decoration like this:
Code:
[COLOR="SeaGreen"]--===============================================================================================================
-- Traits
--===============================================================================================================[/COLOR]
INSERT INTO Traits
(Type, Description, ShortDescription, CultureFromKills)
VALUES ('TRAIT_GENERIC', 'TXT_KEY_TRAIT_GENERIC', 'TXT_KEY_TRAIT_GENERIC_SHORT', 100);
[COLOR="SeaGreen"]--===============================================================================================================
--===============================================================================================================[/COLOR]
Very nice, and keeps things easier to look at.
4.2. Stealing from other tables
Another thing that is a lot easier in SQL than in XML is stealing data from other tables. Say you want to add a Building, but since it's a Temple replacement you want it to be a Temple just with no mantenaince cost (let's imagine you also want the icon and the text and description, because it's a dummy UB)... In XML you'd have to copy the whole BUILDING_TEMPLE table with all its values... in SQL you need somethign like this:
Code:
INSERT INTO Buildings
([B]Type,[/B] BuildingClass, MaxStartEra, Cost, [B]GoldMaintenance,[/B] PrereqTech, Description, Civilopedia, Strategy, ArtDefineTag, MinAreaSize, ConquestProb, HurryCostModifier, IconAtlas, PortraitIndex)
SELECT [B]'BUILDING_DUMMY_TEMPLE'[/B], BuildingClass, MaxStartEra, Cost, [B]0,[/B] PrereqTech, Description, Civilopedia, Strategy, ArtDefineTag, MinAreaSize, ConquestProb, HurryCostModifier, IconAtlas, PortraitIndex
FROM Buildings WHERE (Type = 'BUILDING_TEMPLE');
Now, there are some new things here, of course. We'll explain them now... the first line is easy, it's just a INSERT INTO thing, like you've seen before.
The next line is odd, instead of VALUES it has a SELECT... and the things after select are not between ()... This means you're going to "select" some of the values from another existing Building type (the Temple)... That's why everything is just the same BUT the building type (because its another building, BUILDING_DUMMY_TEMPLE) and the GoldManteinance (which is now 0)...
Then it says FROM Buildings WHERE (Type = 'BUILDING_TEMPLE')... This means, Insert these stuff by selecting the valuse from the "Buildings" table, where the type of the building is BUILDING_TEMPLE... this is how it selects the right values


4.3. Easier mistake checking
In XML you commit one mistake in one file, and the whole file ruins itself.. You suddenly have a whole civ not working and you don't even know why.
In SQL, every single mistake is individual. So, if you only got your mistake in setting the UnitClassOverrides, the civ will exist, just without a UU (so you'll know faster where the mistake was at)... or if you got the issue at the Buildings yield,your building will exist, but without the yield. Is a lot easier and more relaxing

4.4. Putting together a lot of Rows
Another advantage is putting together a lot of rows... Let's see how you use XML to put spies to your civ:
Spoiler :
Code:
<Civilization_SpyNames>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_0</SpyName>
</Row>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_1</SpyName>
</Row>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_2</SpyName>
</Row>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_3</SpyName>
</Row>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_4</SpyName>
</Row>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_5</SpyName>
</Row>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_6</SpyName>
</Row>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_7</SpyName>
</Row>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_8</SpyName>
</Row>
<Row>
<CivilizationType>CIVILIZATION_LEUGI_PHILISTINE</CivilizationType>
<SpyName>TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_9</SpyName>
</Row>
</Civilization_SpyNames>
A long and boring code. Now let's see it in SQL:
Code:
INSERT INTO Civilization_SpyNames
(CivilizationType, SpyName)
VALUES ('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_0'),
('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_1'),
('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_2'),
('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_3'),
('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_4'),
('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_5'),
('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_6'),
('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_7'),
('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_8'),
('CIVILIZATION_LEUGI_PHILISTINE', 'TXT_KEY_SPY_NAME_LEUGI_PHILISTINE_9');
You no longer need to scroll down that much, and you don't need that many <Row>s everywhere. Now, as you can see, to separate each line you just need a comma ( , ) instead of a semicolon ( ; ) which only goes in the last one.
For another example, I'll just show you this:
Code:
--==========================================================================================================================
-- Building Classes
--==========================================================================================================================
INSERT INTO BuildingClasses
(Type, DefaultBuilding, Description)
VALUES ('BUILDINGCLASS_HAITI_BONUS', 'BUILDING_HAITI_BONUS', 'TXT_KEY_TRAIT_LEUGI_HAITI_SHORT'),
('BUILDINGCLASS_HAITI_CHECK', 'BUILDING_HAITI_CHECK', 'TXT_KEY_TRAIT_LEUGI_HAITI_SHORT'),
('BUILDINGCLASS_HAITI_IDEOLOGY', 'BUILDING_HAITI_IDEOLOGY', 'TXT_KEY_TRAIT_LEUGI_HAITI_SHORT'),
('BUILDINGCLASS_HAITI_IDEOLOGY_0', 'BUILDING_HAITI_IDEOLOGY_0', 'TXT_KEY_TRAIT_LEUGI_HAITI_SHORT'),
('BUILDINGCLASS_HAITI_TOURISM', 'BUILDING_HAITI_TOURISM', 'TXT_KEY_TRAIT_LEUGI_HAITI_SHORT');
This adds all Building Classes I needed in Haiti, in just a few easy to look lines

4.5. More Advanced Advantages and Resources
This tutorial ends here, but if you're willing there are some more advanced techniques to use in SQL. Some links if you're interested:
- SQL Cheat Sheet: A simple guide to some of the features and comparisons with XML. You can also see how to update and delete rows in SQL (again, faster than XML
)
- Adding New Tables with SQL: For this you'll also need some Lua knowledge, but TLDR you can use SQL to add new Tables for your own evil needs without touching the DLL (you need Lua so the tables do something, of course)
- SQL Trigger Magic: SQL triggers are fairly advanced, and you'll probably need some practice with SQL without trying these ones. However, they are also really useful. Allowing you to wait before all mods add Civilizations without even knowing their mod ids, or changing all Buildings to have the same Manteinance Cost... all of that is easily possible with SQL.
The End
Enjoy as you are assimilated to the one true master code

(XML is still useful for changing/adding the Pedia texts and descriptions btw)
For any questions, blasphemies or whatever, just post them.