Complete guide to installing the Countries States Cities database in Microsoft SQL Server with enterprise features
Microsoft SQL Server is a powerful enterprise-grade relational database management system. This guide covers installing the Countries States Cities database in SQL Server using the provided SQL scripts.
SQL Server installation typically takes 5-10 minutes and requires approximately 250MB of disk space.
SQL Server provides advanced enterprise features like partitioning, columnstore indexes, and in-memory processing that can significantly improve performance for large datasets.
Adjust the file paths according to your SQL Server data directory. Default is usually C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA\.
2
Execute SQL Script
Open SSMS and connect to your server
Open a new query window
Set the database context: USE [world]
Open the sqlserver/world.sql file
Execute the script (F5)
The script includes table creation, data insertion, and index creation optimized for SQL Server.
3
Verify Installation
Copy
Ask AI
USE [world];SELECT 'countries' as table_name, COUNT(*) as record_count FROM countriesUNION ALLSELECT 'states', COUNT(*) FROM statesUNION ALLSELECT 'cities', COUNT(*) FROM cities;
sqlcmd -S localhost -E -d world -i sqlserver/world.sql
Use -U username -P password instead of -E if not using Windows Authentication.
3
Verify Installation
Copy
Ask AI
sqlcmd -S localhost -E -d world -Q "SELECT 'countries' as table_name, COUNT(*) as count FROM countriesUNION ALL SELECT 'states', COUNT(*) FROM states UNION ALL SELECT 'cities', COUNT(*) FROM cities"
USE master;CREATE LOGIN [csc_user] WITH PASSWORD = 'SecurePassword123!', DEFAULT_DATABASE = [world], CHECK_POLICY = ON, CHECK_EXPIRATION = OFF;
Use a strong password that meets your organization’s security requirements.
2
Create Database User
Copy
Ask AI
USE [world];CREATE USER [csc_user] FOR LOGIN [csc_user];-- Grant permissionsALTER ROLE [db_datareader] ADD MEMBER [csc_user];-- Add db_datawriter if write access needed-- ALTER ROLE [db_datawriter] ADD MEMBER [csc_user];
-- Performance indexes optimized for SQL ServerCREATE NONCLUSTERED INDEX IX_Countries_ISO2 ON countries (iso2) INCLUDE (name, region);CREATE NONCLUSTERED INDEX IX_Countries_Region ON countries (region) INCLUDE (name, iso2, iso3);CREATE NONCLUSTERED INDEX IX_States_CountryID ON states (country_id) INCLUDE (name, state_code);CREATE NONCLUSTERED INDEX IX_Cities_CountryID ON cities (country_id) INCLUDE (name, state_id, latitude, longitude);CREATE NONCLUSTERED INDEX IX_Cities_StateID ON cities (state_id) INCLUDE (name, latitude, longitude);CREATE NONCLUSTERED INDEX IX_Cities_Coordinates ON cities (latitude, longitude) INCLUDE (name, country_name, state_name);
-- Create memory-optimized filegroup (SQL Server 2014+)ALTER DATABASE [world] ADD FILEGROUP [world_memory] CONTAINS MEMORY_OPTIMIZED_DATA;ALTER DATABASE [world] ADD FILE ( name='world_memory', filename='C:\Data\world_memory') TO FILEGROUP [world_memory];-- Create memory-optimized table for frequently accessed countriesCREATE TABLE countries_memory ( id INT NOT NULL PRIMARY KEY NONCLUSTERED, name NVARCHAR(100) NOT NULL, iso2 NCHAR(2) NOT NULL, iso3 NCHAR(3) NOT NULL, region NVARCHAR(100), INDEX IX_Countries_Memory_ISO2 NONCLUSTERED (iso2), INDEX IX_Countries_Memory_Region NONCLUSTERED (region)) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);
-- Get table informationSELECT t.name AS TableName, s.name AS SchemaName, p.rows AS RecordCount, CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS TotalSpaceMB, CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2) AS NUMERIC(36, 2)) AS UsedSpaceMBFROM sys.tables tINNER JOIN sys.indexes i ON t.object_id = i.object_idINNER JOIN sys.partitions p ON i.object_id = p.object_id AND i.index_id = p.index_idINNER JOIN sys.allocation_units a ON p.partition_id = a.container_idINNER JOIN sys.schemas s ON t.schema_id = s.schema_idWHERE t.name IN ('countries', 'states', 'cities') AND i.index_id <= 1GROUP BY t.name, s.name, p.rowsORDER BY t.name;
using System;using System.Collections.Generic;using System.Data;using System.Data.SqlClient;public class WorldDatabase : IDisposable{ private readonly string _connectionString; private SqlConnection _connection; public WorldDatabase(string connectionString) { _connectionString = connectionString; _connection = new SqlConnection(_connectionString); _connection.Open(); } public List<Country> GetCountries(string region = null, int? limit = null) { var countries = new List<Country>(); var query = "SELECT id, name, iso2, iso3, region FROM countries"; var parameters = new List<SqlParameter>(); if (!string.IsNullOrEmpty(region)) { query += " WHERE region = @region"; parameters.Add(new SqlParameter("@region", region)); } if (limit.HasValue) { query += $" ORDER BY name OFFSET 0 ROWS FETCH NEXT {limit} ROWS ONLY"; } using var command = new SqlCommand(query, _connection); command.Parameters.AddRange(parameters.ToArray()); using var reader = command.ExecuteReader(); while (reader.Read()) { countries.Add(new Country { Id = reader.GetInt32("id"), Name = reader.GetString("name"), Iso2 = reader.GetString("iso2"), Iso3 = reader.GetString("iso3"), Region = reader.IsDBNull("region") ? null : reader.GetString("region") }); } return countries; } public List<City> GetCitiesByCountry(string countryName, int? limit = null) { var cities = new List<City>(); var query = @" SELECT name, latitude, longitude, state_name, country_name FROM cities WHERE country_name = @countryName"; if (limit.HasValue) { query += $" ORDER BY name OFFSET 0 ROWS FETCH NEXT {limit} ROWS ONLY"; } using var command = new SqlCommand(query, _connection); command.Parameters.AddWithValue("@countryName", countryName); using var reader = command.ExecuteReader(); while (reader.Read()) { cities.Add(new City { Name = reader.GetString("name"), Latitude = reader.IsDBNull("latitude") ? null : reader.GetDouble("latitude"), Longitude = reader.IsDBNull("longitude") ? null : reader.GetDouble("longitude"), StateName = reader.IsDBNull("state_name") ? null : reader.GetString("state_name"), CountryName = reader.GetString("country_name") }); } return cities; } public void Dispose() { _connection?.Dispose(); }}// Usagestring connectionString = "Server=localhost;Database=world;Trusted_Connection=true;";using var db = new WorldDatabase(connectionString);var countries = db.GetCountries("Europe", 5);foreach (var country in countries){ Console.WriteLine($"{country.Name} ({country.Iso2})");}
-- Add geography column for precise spatial operationsALTER TABLE cities ADD geolocation GEOGRAPHY;-- Update geography dataUPDATE cities SET geolocation = geography::Point(latitude, longitude, 4326)WHERE latitude IS NOT NULL AND longitude IS NOT NULL;-- Create spatial indexCREATE SPATIAL INDEX IX_Cities_Geolocation ON cities (geolocation);
-- Create full-text catalogCREATE FULLTEXT CATALOG ft_world_catalog;-- Create full-text indexesCREATE FULLTEXT INDEX ON countries (name) KEY INDEX PK_Countries;CREATE FULLTEXT INDEX ON cities (name) KEY INDEX PK_Cities;
-- Create full backupBACKUP DATABASE [world] TO DISK = 'C:\Backups\world_full_backup.bak'WITH FORMAT, COMPRESSION, CHECKSUM;-- Verify backupRESTORE VERIFYONLY FROM DISK = 'C:\Backups\world_full_backup.bak';
-- Check index fragmentationSELECT OBJECT_NAME(i.object_id) AS TableName, i.name AS IndexName, s.avg_fragmentation_in_percent, s.page_countFROM sys.dm_db_index_physical_stats(DB_ID(), NULL, NULL, NULL, 'DETAILED') sINNER JOIN sys.indexes i ON s.object_id = i.object_id AND s.index_id = i.index_idWHERE s.avg_fragmentation_in_percent > 10ORDER BY s.avg_fragmentation_in_percent DESC;-- Rebuild fragmented indexesALTER INDEX ALL ON countries REBUILD WITH (ONLINE = ON);ALTER INDEX ALL ON cities REBUILD WITH (ONLINE = ON);
Use SQL Server Maintenance Plans to automate backup, index maintenance, and statistics updates for production environments.