스키마는 테이블의 명명 된 모음입니다. 스키마에는 뷰, 인덱스, 시퀀스, 데이터 유형, 연산자 및 함수가 포함될 수도 있습니다. 스키마는 운영 체제 레벨의 디렉토리와 유사하지만 스키마를 중첩 할 수 없다는 점이 다릅니다

 

스키마란

- 테이블의 명명된 모음.

- 뷰, 인덱스, 시퀀스, 데이터 유형, 연산자, 함수가 포함될 수 있음.

- 중첩 되지 않음.

 

스키마를 먼저 생성합니다.

CREATE SCHEMA MYSCHEMA;

 

생성된 스키마에 테이블을 생성합니다.

CREATE TABLE MYSCHEMA.COMPANY
(
    ID       INT              NOT NULL PRIMARY KEY
   ,NAME     VARCHAR (20)     NOT NULL
   ,AGE      INT              NOT NULL
   ,ADDRESS  CHAR (25)
   ,SALARY   DECIMAL (18, 2)
);

 

테이블 삭제하기 입니다.

 

COMPANY 라는 이름을 가지는 테이블을 삭제 합니다.

DROP TABLE COMPANY

1개의 기본키를 가지는 테이블 생성하기.

CREATE TABLE COMPANY
(
	ID      INT PRIMARY KEY NOT NULL,
	NAME    TEXT				NOT NULL,
	AGE     INT					NOT NULL,
	ADDRESS CHAR(50),
	SALARY  REAL
);

 

PostgreSQL 데이터 타입 테이블 입니다.

 

데이터 타입 별칭 설명
bigint int8 부호있는 8 바이트 정수
bigserial serial8 자동 증가 8 바이트 정수
bit [ (n) ]   고정 길이 비트 문자열
bit varying [ (n) ] varbit [ (n) ] 가변 길이 비트 열
boolean bool 논리 부울 (true/false)
box   rectangular box on a plane
bytea   이진 데이터 (바이트 배열)
character [ (n) ] char [ (n) ] 고정 길이 문자열
character varying [ (n) ] varchar [ (n) ] 가변 길이 문자열
cidr   IPv4 혹은 IPv6 네트워크 주소
circle   circle on a plane
date   달력 날짜 (년, 월, 일)
double precision float8 배정 밀도 부동 소수점 수 (8 bytes)
inet   IPv4 혹은IPv6 호스트 주소
integer int, int4 부호가 있는 4 바이트 정수
interval [ fields ] [ (p) ]   시간 범위
json   텍스트 JSON 데이터
jsonb   이진 JSON 데이터, decomposed
line   infinite line on a plane
lseg   line segment on a plane
macaddr   MAC 주소
macaddr8   맥 주소 (EUI-64 format)
money   통화량
numeric [ (p, s) ] decimal [ (p, s) ] 선택 가능한 정밀도의 정확한 숫자
path   geometric path on a plane
pg_lsn   PostgreSQL 로그 시퀀스 번호
point   geometric point on a plane
polygon   closed geometric path on a plane
real float4 단 정밀도 부동 소수점 수 (4 바이트)
smallint int2 부호가 있는 2 바이트 정수
smallserial serial2 2 바이트 정수 자동 증가
serial serial4 4 바이트 정수 자동 증가
text   가변 길이 문자열
time [ (p) ] [ without time zone ]   시간대 (시간대 없음)
time [ (p) ] with time zone timetz 시간대를 포함한 시간대
timestamp [ (p) ] [ without time zone ]   날짜 및 시간 (시간대 없음)
timestamp [ (p) ] with time zone timestamptz 날짜 및 시간 (시간대 포함)
tsquery   텍스트 검색 쿼리
tsvector   텍스트 검색 문서
txid_snapshot   사용자 수준 트랜잭션 ID 스냅 샷
uuid   보편적으로 고유한 식별자
xml   XML 데이터

DevExpress를 사용하여 로컬 드라이브에서 TreeList를 사용하여 디렉토리 구조를 확인할 수 있습니다.

 

예제 결과 입니다.

using System.IO;
using System.Windows.Forms;

using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Columns;
using DevExpress.XtraTreeList.Nodes;

namespace DevTestForm
{
    /// <summary>
    /// 메인폼 클래스 입니다.
    /// </summary>
    public partial class MainForm : Form
    {   
        // Constructor (Public)

        #region MainForm() - 생성자 입니다.

        /// <summary>
        /// 생성자 입니다.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
            InitTreeList();
            InitData();

            #region 이벤트를 설정합니다.

            #endregion
        }

        #endregion

        private void InitTreeList()
        {
            TreeListColumn fullNameColumn = new TreeListColumn();
            TreeListColumn nameColumn     = new TreeListColumn();
            TreeListColumn typeColumn     = new TreeListColumn();
            TreeListColumn sizeColumn     = new TreeListColumn();

            fullNameColumn.Caption   = "FullName";
            fullNameColumn.FieldName = "FullName";

            nameColumn.Caption      = "Name";
            nameColumn.FieldName    = "Name";
            nameColumn.MinWidth     = 27;
            nameColumn.VisibleIndex = 0;
            nameColumn.Width        = 274;

            typeColumn.Caption      = "Type";
            typeColumn.FieldName    = "Type";
            typeColumn.VisibleIndex = 1;
            typeColumn.Width        = 112;

            sizeColumn.AppearanceCell.Options.UseTextOptions = true;
            sizeColumn.AppearanceCell.TextOptions.HAlignment = DevExpress.Utils.HorzAlignment.Far;
            sizeColumn.Caption                               = "Size(Bytes)";
            sizeColumn.FieldName                             = "Size";
            sizeColumn.Format.FormatType                     = DevExpress.Utils.FormatType.Numeric;
            sizeColumn.Format.FormatString                   = "n0";
            sizeColumn.VisibleIndex                          = 2;
            sizeColumn.Width                                 = 123;

            this.devTreeList.Columns.AddRange(new TreeListColumn[]
            {
                fullNameColumn, nameColumn, typeColumn, sizeColumn
            });

            this.devTreeList.Dock                                   = DockStyle.Fill;
            this.devTreeList.OptionsBehavior.AutoChangeParent       = false;
            this.devTreeList.OptionsBehavior.AutoNodeHeight         = false;
            this.devTreeList.OptionsBehavior.CloseEditorOnLostFocus = false;
            this.devTreeList.OptionsBehavior.Editable               = false;
            this.devTreeList.OptionsBehavior.ShowToolTips           = false;
            this.devTreeList.OptionsBehavior.SmartMouseHover        = false;
            this.devTreeList.OptionsSelection.KeepSelectedOnClick   = false;

            this.devTreeList.StateImageList = this.imageList;

            #region 이벤트를 설정합니다.

            this.devTreeList.AfterCollapse += devTreeList_AfterCollapse;
            this.devTreeList.AfterExpand   += devTreeList_AfterExpand;
            this.devTreeList.BeforeExpand  += devTreeList_BeforeExpand;

            #endregion

        }

        // Event Method (Private)

        #region devTreeList_AfterCollapse(sender, e)

        /// <summary>
        /// 트리리스트의 노드가 접힌 후에 동작합니다.
        /// </summary>
        /// <param name="sender">이벤트 발생자 입니다.</param>
        /// <param name="e">이벤트 인자 입니다.</param>
        private void devTreeList_AfterCollapse(object sender, NodeEventArgs e)
        {
            if(e.Node.StateImageIndex != 1)
            { 
                e.Node.StateImageIndex = 0;
            }
        }

        #endregion

        #region devTreeList_AfterExpand(sender, e)

        /// <summary>
        /// 트리리스트의 노드가 펼쳐진 후에 동작합니다.
        /// </summary>
        /// <param name="sender">이벤트 발생자 입니다.</param>
        /// <param name="e">이벤트 인자 입니다.</param>
        private void devTreeList_AfterExpand(object sender, NodeEventArgs e)
        {
            if (e.Node.StateImageIndex != 1)
            {
                e.Node.StateImageIndex = 2;
            }
        }

        #endregion

        #region devTreeList_BeforeExpand(sender, e)

        /// <summary>
        /// 트리리스트의 노드가 펼쳐지기 전에 동작합니다.
        /// </summary>
        /// <param name="sender">이벤트 발생자 입니다.</param>
        /// <param name="e">이벤트 인자 입니다.</param>
        private void devTreeList_BeforeExpand(object sender, BeforeExpandEventArgs e)
        {
            if(e.Node.Tag != null)
            { 
                Cursor currentCursor = Cursor.Current;
                Cursor.Current = Cursors.WaitCursor;
                InitFolders(e.Node.GetDisplayText("FullName"), e.Node);
                e.Node.Tag = null;
                Cursor.Current = currentCursor;
            }
        }

        #endregion

        #region InitData() - 데이터를 초기화합니다.

        /// <summary>
        /// 데이터를 초기화합니다.
        /// </summary>
        private void InitData()
        { 
            InitFolders(Directory.GetDirectoryRoot(Directory.GetCurrentDirectory()), null);
        }

        #endregion

        #region InitFolders(path, node) - 폴더를 초기화 합니다.

        /// <summary>
        /// 폴더를 초기화 합니다.
        /// </summary>
        /// <param name="path">경로 입니다.</param>
        /// <param name="node">노드 입니다.</param>
        private void InitFolders(string path, TreeListNode node)
        {
            this.devTreeList.BeginUnboundLoad();
            
            TreeListNode treeListNode;
            DirectoryInfo directoryInfo;

            try
            {
                string[] root = Directory.GetDirectories(path);

                foreach(string item in root)
                {
                    try
                    {
                        directoryInfo = new DirectoryInfo(item);
                        treeListNode                 = this.devTreeList.AppendNode
                        (
                            new object[] { item, directoryInfo.Name, "Folder", null }, node
                        );
                        treeListNode.StateImageIndex = 0;
                        treeListNode.HasChildren     = HasFiles(item);

                        if (treeListNode.HasChildren)
                        {
                            treeListNode.Tag = true;
                        }
                    }
                    catch{ }
                    
                }
            }
            catch{ }

            InitFiles(path, node);
            this.devTreeList.EndUnboundLoad();
        }

        #endregion

        #region InitFiles(path, node) - 파일을 초기화 합니다.

        /// <summary>
        /// 파일을 초기화 합니다.
        /// </summary>
        /// <param name="path">경로 입니다.</param>
        /// <param name="node">노드 입니다.</param>
        private void InitFiles(string path, TreeListNode node)
        {
            TreeListNode treeListNode;

            FileInfo fileInfo;

            try
            {
                string[] root = Directory.GetFiles(path);

                foreach(string item in root)
                {
                    fileInfo = new FileInfo(item);

                    treeListNode                 = this.devTreeList.AppendNode
                    (
                        new object[] { item, fileInfo.Name, "File", fileInfo.Length }, node
                    );

                    treeListNode.StateImageIndex = 1;
                    treeListNode.HasChildren     = false;
                }
            }
            catch { }
        }

        #endregion

        #region HasFiles(path) - 파일의 존재 여부를 확인합니다.

        /// <summary>
        /// 파일의 존재 여부를 확인합니다.
        /// </summary>
        /// <param name="path">경로 입니다.</param>
        /// <returns>파일 유무를 리턴합니다.</returns>
        private bool HasFiles(string path)
        {
            string[] root = Directory.GetFiles(path);

            if(root.Length > 0)
            { 
                return true;
            }

            root = Directory.GetDirectories(path);

            if(root.Length > 0)
            { 
                return true;
            }

            return false;
        }

        #endregion
    }
}

DevExpress에서 TreeList에서 노드 추가하기 입니다.

 

TreeList에서 노드 추가한 결과 입니다.

using System.Windows.Forms;

using DevExpress.XtraEditors;
using DevExpress.XtraLayout;
using DevExpress.XtraTreeList;
using DevExpress.XtraTreeList.Columns;
using DevExpress.XtraTreeList.Nodes;

namespace DevTestForm
{
    /// <summary>
    /// 메인폼 클래스 입니다.
    /// </summary>
    public partial class MainForm : Form
    {   
        // Constructor (Public)

        #region MainForm() - 생성자 입니다.

        /// <summary>
        /// 생성자 입니다.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            CreateColumns(this.devTreeList);
            CreateNodes(this.devTreeList);

            #region 이벤트를 설정합니다.

            #endregion
        }

        #endregion


        #region CreateColumns(treeList) - 컬럼을 생성합니다.

        /// <summary>
        /// 컬럼을 생성합니다.
        /// </summary>
        /// <param name="treeList">TreeList 입니다.</param>
        private void CreateColumns(TreeList treeList)
        { 
            treeList.BeginUpdate();

            TreeListColumn column1 = treeList.Columns.Add();
            column1.Caption      = "Customer";
            column1.VisibleIndex = 0;

            TreeListColumn column2 = treeList.Columns.Add();
            column2.Caption      = "Location";
            column2.VisibleIndex = 1;

            TreeListColumn column3 = treeList.Columns.Add();
            column3.Caption      = "Phone";
            column3.VisibleIndex = 2;

            treeList.EndUpdate();
        }

        #endregion

        #region CreateNodes(treeList)

        /// <summary>
        /// 노드를 생성합니다.
        /// </summary>
        /// <param name="treeList">TreeList 입니다.</param>
        private void CreateNodes(TreeList treeList)
        { 
            treeList.BeginUnboundLoad();

            TreeListNode parentForRootNodes = null;
            TreeListNode rootNode = treeList.AppendNode
            (
                new object[]{"AAAAAA", "BBBBBB", "000-0000-0000"}, parentForRootNodes
            );

            treeList.AppendNode
            (
                new object[] { "CCCCCC", "DDDDDDD", "1111-1111-1111" }, rootNode
            );

            treeList.AppendNode
            (
                new object[] { "ABB", "ADDADA", "222-2222-1111" }, rootNode
            );

            treeList.EndUnboundLoad();
        }

        #endregion

    }
}

DevExpress로 탭 그룹을 생성하는 코드 입니다.

 

탭 그룹 생성 예제

 

using System.Windows.Forms;

using DevExpress.XtraEditors;
using DevExpress.XtraLayout;

namespace DevTestForm
{
    /// <summary>
    /// 메인폼 클래스 입니다.
    /// </summary>
    public partial class MainForm : Form
    {   
        // Constructor (Public)

        #region MainForm() - 생성자 입니다.

        /// <summary>
        /// 생성자 입니다.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            CreateTabGroup();

            #region 이벤트를 설정합니다.

            #endregion
        }

        #endregion

        #region CreateTabGroup() - 탭 그룹을 생성합니다.

        /// <summary>
        /// 탭 그룹을 생성합니다.
        /// </summary>
        private void CreateTabGroup()
        { 
            LayoutControl layoutControl = new LayoutControl();

            layoutControl.Dock = DockStyle.Fill;
            this.Controls.Add(layoutControl);

            layoutControl.BeginUpdate();

            try
            {
                // 루트 그룹에 탭 그룹을 생성합니다.
                TabbedControlGroup tabbedGroup = layoutControl.Root.AddTabbedGroup();
                tabbedGroup.Name = "TabbedGroup";

                // 하나의 탭에 사진 그룹을 추가합니다.
                LayoutControlGroup groupImage = tabbedGroup.AddTabPage() as LayoutControlGroup;
                groupImage.Name = "layoutGroupPhoto";
                groupImage.Text = "Photo";

                // 이미지 그룹에 이미지가 출력되도록 레이아웃 아이템을 추가합니다.
                LayoutControlItem layoutItemImage = groupImage.AddItem();
                layoutItemImage.Name        = "layoutItemPhoto";
                layoutItemImage.Control     = new PictureEdit(){ Name = "pictureEdutPhoto"};
                layoutItemImage.TextVisible = false;

                // 하나의 탭에 노트 그룹을 추가합니다.
                LayoutControlGroup groupNotes = tabbedGroup.AddTabPage() as LayoutControlGroup;
                groupNotes.Name = "layoutGroupNotes";
                groupNotes.Text = "Notes";

                // 노트 그룹에 노트가 출력되도록 레이아웃 아이템을 추가합니다.
                LayoutControlItem layoutItemNotes = groupNotes.AddItem();
                layoutItemNotes.Name        = "layoutItemNotes";
                layoutItemNotes.Control     = new MemoEdit(){ Name = "memoEditNotes"};
                layoutItemNotes.TextVisible = false;

                // 첫번째 탭이 출력됩니다.
                tabbedGroup.SelectedTabPage = groupImage;
            }
            finally
            {
                layoutControl.EndUpdate();
            }

        }

        #endregion
    }
}

입력된 URL을 얼마만에 받을 수 있는지 확인하는 예제 입니다.

 

한 버튼은 동기 방식으로 동작을 하고

 

다른 한 버튼은 비동기 방식 및 병렬 처리를 하여 동작을 합니다.

 

동기 방식일 경우에는 시간도 오래 걸리고 버튼 클릭 시 다른 UI들이 반응을 하지 않지만

 

비동기 방식일 경우에는 시간도 단축되며 버튼 클릭 하여도 다른 UI들의 동작도 가능합니다.

 

실행 예제 입니다.

 

비동기 호출의 병렬 처리 하기 입니다.

 

아래의 예제는 병렬 처리 하기 전입니다.

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace TaskSample
{
    class Program
    {

        static void Main(string[] args)
        {
            int result3 = Method3();
            int result5 = Method5();

            Console.WriteLine(result3 + result5);
        }

        private static int Method3()
        {
            Thread.Sleep(3000); // 3초가 걸리는 작업을 대신해서 sleep 처리
            return 3;
        }

        private static int Method5()
        {
            Thread.Sleep(5000); // 5초가 걸리는 작업을 대신해서 sleep 처리
            return 5;
        }
    }
}

 

병렬로 처리 했을 경우 8초 걸릴 작업을 5초로 줄일 수 있습니다.

아래의 예제는 병렬 처리 방식이며 Task<TResult> 타입으로 구현한 예제 입니다.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace TaskSample
{
    class Program
    {

        static void Main(string[] args)
        {
            // Task를 이용해 병렬로 처리하기
            var task3 = Method3Async();
            var task5 = Method5Async();

            // task3 작업과 task5 작업이 완료될 때까지 현재 스레드를 대기
            Task.WaitAll(task3, task5);

            Console.WriteLine(task3.Result + task5.Result);
        }

        private static Task<int> Method3Async()
        { 
            return Task.Factory.StartNew(() =>
            { 
                Thread.Sleep(3000);

                return 3;
            });
        }

        private static Task<int> Method5Async()
        {
            return Task.Factory.StartNew(() =>
            {
                Thread.Sleep(5000);

                return 5;
            });
        }
    }
}

위의 예제는 모든 작업이 완료 될때까지 대기를 해야합니다.

 

Task<TResult>와 await을 사용하여 동시에 비동기 호출로 처리할 수 있습니다.

using System;
using System.Threading;
using System.Threading.Tasks;

namespace TaskSample
{
    class Program
    {
        static void Main(string[] args)
        {
            // await을 이용하여 병렬로 비동기 호출: 5초 소요됨.
            DoAsyncTask();
            
            Console.ReadLine();
        }

        private static async Task DoAsyncTask()
        {
            var task3 = Method3Async();
            var task5 = Method5Async();

            await Task.WhenAll(task3, task5);

            Console.WriteLine(task3.Result + task5.Result);
        }

        private static Task<int> Method3Async()
        { 
            return Task.Factory.StartNew(() =>
            { 
                Thread.Sleep(3000);

                return 3;
            });
        }

        private static Task<int> Method5Async()
        {
            return Task.Factory.StartNew(() =>
            {
                Thread.Sleep(5000);

                return 5;
            });
        }
    }
}

ReadAllText 메서드를 비동기로 처리하기 입니다.

 

별도의 스레드를 이용하거나 델리게이트의 BeginInvoke로 처리하여 비동기를 적용하는 예제입니다.(복잡함)

using System;
using System.IO;

namespace TaskSample
{
    class Program
    {
        public delegate string ReadAllTextDelegate(string path);

        static void Main(string[] args)
        {
            string filePath = @"C:\windows\system32\drivers\etc\HOSTS";

            ReadAllTextDelegate func = File.ReadAllText;
            func.BeginInvoke(filePath, actionCompleted, func);

            Console.ReadLine();
        }

        static void actionCompleted(IAsyncResult asyncResult)
        {
            ReadAllTextDelegate func = asyncResult.AsyncState as ReadAllTextDelegate;
            string fileText = func.EndInvoke(asyncResult);

            Console.WriteLine(fileText);
        }
    }
}


위의 예제를 Task<TResult>로 바꾸면 await을 이용하여 쉽게 비동기 호출을 적용할 수 있습니다.

 

Async 메서드로 제공되지 않은 모든 동기 방식의 메서드를 비동기로 변환 가능합니다.

using System;
using System.IO;
using System.Threading.Tasks;

namespace TaskSample
{
    class Program
    {
        public delegate string ReadAllTextDelegate(string path);

        static void Main(string[] args)
        {
            string filePath = @"C:\windows\system32\drivers\etc\HOSTS";

            AwaitFileRead(filePath);

            Console.ReadLine();
        }

        static Task<string> ReadAllTextAsync(string filePath)
        {
            return Task.Factory.StartNew(() =>
            {
                return File.ReadAllText(filePath);
            });
        }

        private static async Task AwaitFileRead(string filePath)
        {
            string fileText = await ReadAllTextAsync(filePath);

            Console.WriteLine(fileText);
        }
    }
}

 

+ Recent posts